org.apache.calcite.util.mapping.Mapping Java Examples

The following examples show how to use org.apache.calcite.util.mapping.Mapping. 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: RelFieldTrimmer.java    From calcite with Apache License 2.0 6 votes vote down vote up
/** Creates a project with a dummy column, to protect the parts of the system
 * that cannot handle a relational expression with no columns.
 *
 * @param fieldCount Number of fields in the original relational expression
 * @param input Trimmed input
 * @param originalRelNode Source RelNode for hint propagation (or null if no propagation needed)
 * @return Dummy project
 */
protected TrimResult dummyProject(int fieldCount, RelNode input, RelNode originalRelNode) {
  final RelOptCluster cluster = input.getCluster();
  final Mapping mapping =
      Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, 1);
  if (input.getRowType().getFieldCount() == 1) {
    // Input already has one field (and may in fact be a dummy project we
    // created for the child). We can't do better.
    return result(input, mapping);
  }
  final RexLiteral expr =
      cluster.getRexBuilder().makeExactLiteral(BigDecimal.ZERO);
  relBuilder.push(input);
  relBuilder.project(ImmutableList.of(expr), ImmutableList.of("DUMMY"));
  RelNode newProject = relBuilder.build();
  if (originalRelNode != null) {
    newProject = RelOptUtil.propagateRelHints(originalRelNode, newProject);
  }
  return result(newProject, mapping);
}
 
Example #2
Source File: FilterNLJMergeRule.java    From dremio-oss with Apache License 2.0 6 votes vote down vote up
@Override
public void onMatch(RelOptRuleCall call) {
  FilterPrel filter = call.rel(0);
  NestedLoopJoinPrel join = call.rel(1);

  if ((join.getProjectedFields() == null) || join.getProjectedFields().cardinality() == join.getInputRowType().getFieldCount()) {
    call.transformTo(NestedLoopJoinPrel.create(join.getCluster(), join.getTraitSet(), join.getLeft(), join.getRight(), join.getJoinType(), RelOptUtil.andJoinFilters(join.getCluster().getRexBuilder(), join.getCondition(), filter.getCondition()), join.getProjectedFields()));
  } else {
    // Current filter condition is written based on projected fields on join. In order to push this filter down we need to rewrite filter condition
    final ImmutableBitSet topProjectedColumns = RelOptUtil.InputFinder.bits(filter.getCondition());
    final ImmutableBitSet bottomProjectedColumns = join.getProjectedFields();

    Mapping mapping = Mappings.create(MappingType.SURJECTION, join.getRowType().getFieldCount(), join.getInputRowType().getFieldCount());
    for (Ord<Integer> ord : Ord.zip(bottomProjectedColumns)) {
      if (topProjectedColumns.get(ord.i)) {
        mapping.set(ord.i, ord.e);
      }
    }

    RexShuttle shuttle = new RexPermuteInputsShuttle(mapping);
    RexNode updatedCondition = shuttle.apply(filter.getCondition());

    call.transformTo(NestedLoopJoinPrel.create(join.getCluster(), join.getTraitSet(), join.getLeft(), join.getRight(), join.getJoinType(), RelOptUtil.andJoinFilters(join.getCluster().getRexBuilder(), join.getCondition(), updatedCondition), join.getProjectedFields()));
  }
}
 
Example #3
Source File: ExtendedAggregateExtractProjectRule.java    From flink with Apache License 2.0 6 votes vote down vote up
private List<RelBuilder.AggCall> getNewAggCallList(
	Aggregate oldAggregate,
	RelBuilder relBuilder,
	Mapping mapping) {

	final List<RelBuilder.AggCall> newAggCallList = new ArrayList<>();

	for (AggregateCall aggCall : oldAggregate.getAggCallList()) {
		final RexNode filterArg = aggCall.filterArg < 0 ? null
			: relBuilder.field(Mappings.apply(mapping, aggCall.filterArg));
		newAggCallList.add(
			relBuilder
				.aggregateCall(
					aggCall.getAggregation(),
					relBuilder.fields(Mappings.apply2(mapping, aggCall.getArgList())))
				.distinct(aggCall.isDistinct())
				.filter(filterArg)
				.approximate(aggCall.isApproximate())
				.sort(relBuilder.fields(aggCall.collation))
				.as(aggCall.name));
	}
	return newAggCallList;
}
 
Example #4
Source File: DremioFieldTrimmer.java    From dremio-oss with Apache License 2.0 6 votes vote down vote up
public TrimResult trimFields(
  LimitRel limit,
  ImmutableBitSet fieldsUsed,
  Set<RelDataTypeField> extraFields
) {
  final RelDataType rowType = limit.getRowType();
  final int fieldCount = rowType.getFieldCount();
  final RelNode input = limit.getInput();

  final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
  TrimResult trimResult =
    trimChild(limit, input, fieldsUsed, inputExtraFields);
  RelNode newInput = trimResult.left;
  final Mapping inputMapping = trimResult.right;

  if (newInput == input
    && inputMapping.isIdentity()
    && fieldsUsed.cardinality() == fieldCount) {
    return result(limit, Mappings.createIdentity(fieldCount));
  }
  return result(limit.copy(newInput.getTraitSet(), ImmutableList.of(newInput)), inputMapping);
}
 
Example #5
Source File: RelOptUtil.java    From Bats with Apache License 2.0 6 votes vote down vote up
@Deprecated // to be removed before 2.0
public static RelNode projectMapping(RelNode rel, Mapping mapping, List<String> fieldNames,
        RelFactories.ProjectFactory projectFactory) {
    assert mapping.getMappingType().isSingleSource();
    assert mapping.getMappingType().isMandatorySource();
    if (mapping.isIdentity()) {
        return rel;
    }
    final List<String> outputNameList = new ArrayList<>();
    final List<RexNode> exprList = new ArrayList<>();
    final List<RelDataTypeField> fields = rel.getRowType().getFieldList();
    final RexBuilder rexBuilder = rel.getCluster().getRexBuilder();
    for (int i = 0; i < mapping.getTargetCount(); i++) {
        final int source = mapping.getSource(i);
        final RelDataTypeField sourceField = fields.get(source);
        outputNameList.add(((fieldNames == null) || (fieldNames.size() <= i) || (fieldNames.get(i) == null))
                ? sourceField.getName()
                : fieldNames.get(i));
        exprList.add(rexBuilder.makeInputRef(rel, source));
    }
    return projectFactory.createProject(rel, exprList, outputNameList);
}
 
Example #6
Source File: ExtendedAggregateExtractProjectRule.java    From flink with Apache License 2.0 6 votes vote down vote up
private List<RelBuilder.AggCall> getNewAggCallList(
	Aggregate oldAggregate,
	RelBuilder relBuilder,
	Mapping mapping) {

	final List<RelBuilder.AggCall> newAggCallList = new ArrayList<>();

	for (AggregateCall aggCall : oldAggregate.getAggCallList()) {
		final RexNode filterArg = aggCall.filterArg < 0 ? null
			: relBuilder.field(Mappings.apply(mapping, aggCall.filterArg));
		newAggCallList.add(
			relBuilder
				.aggregateCall(
					aggCall.getAggregation(),
					relBuilder.fields(Mappings.apply2(mapping, aggCall.getArgList())))
				.distinct(aggCall.isDistinct())
				.filter(filterArg)
				.approximate(aggCall.isApproximate())
				.sort(relBuilder.fields(aggCall.collation))
				.as(aggCall.name));
	}
	return newAggCallList;
}
 
Example #7
Source File: RelMdPredicates.java    From calcite with Apache License 2.0 6 votes vote down vote up
private void infer(RexNode predicates, Set<RexNode> allExprs,
    List<RexNode> inferredPredicates, boolean includeEqualityInference,
    ImmutableBitSet inferringFields) {
  for (RexNode r : RelOptUtil.conjunctions(predicates)) {
    if (!includeEqualityInference
        && equalityPredicates.contains(r)) {
      continue;
    }
    for (Mapping m : mappings(r)) {
      RexNode tr = r.accept(
          new RexPermuteInputsShuttle(m, joinRel.getInput(0),
              joinRel.getInput(1)));
      // Filter predicates can be already simplified, so we should work with
      // simplified RexNode versions as well. It also allows prevent of having
      // some duplicates in in result pulledUpPredicates
      RexNode simplifiedTarget =
          simplify.simplifyFilterPredicates(RelOptUtil.conjunctions(tr));
      if (checkTarget(inferringFields, allExprs, tr)
          && checkTarget(inferringFields, allExprs, simplifiedTarget)) {
        inferredPredicates.add(simplifiedTarget);
        allExprs.add(simplifiedTarget);
      }
    }
  }
}
 
Example #8
Source File: RelFieldTrimmer.java    From Bats with Apache License 2.0 6 votes vote down vote up
protected TrimResult result(RelNode r, final Mapping mapping) {
    final RexBuilder rexBuilder = relBuilder.getRexBuilder();
    for (final CorrelationId correlation : r.getVariablesSet()) {
        r = r.accept(new CorrelationReferenceFinder() {
            @Override
            protected RexNode handle(RexFieldAccess fieldAccess) {
                final RexCorrelVariable v = (RexCorrelVariable) fieldAccess.getReferenceExpr();
                if (v.getCorrelationId().equals(correlation)
                        && v.getType().getFieldCount() == mapping.getSourceCount()) {
                    final int old = fieldAccess.getField().getIndex();
                    final int new_ = mapping.getTarget(old);
                    final RelDataTypeFactory.Builder typeBuilder = relBuilder.getTypeFactory().builder();
                    for (int target : Util.range(mapping.getTargetCount())) {
                        typeBuilder.add(v.getType().getFieldList().get(mapping.getSource(target)));
                    }
                    final RexNode newV = rexBuilder.makeCorrel(typeBuilder.build(), v.getCorrelationId());
                    if (old != new_) {
                        return rexBuilder.makeFieldAccess(newV, new_);
                    }
                }
                return fieldAccess;
            }
        });
    }
    return new TrimResult(r, mapping);
}
 
Example #9
Source File: MaterializedViewRule.java    From calcite with Apache License 2.0 6 votes vote down vote up
/**
 * Replaces all the input references by the position in the
 * input column set. If a reference index cannot be found in
 * the input set, then we return null.
 */
protected RexNode shuttleReferences(final RexBuilder rexBuilder,
    final RexNode node, final Mapping mapping) {
  try {
    RexShuttle visitor =
        new RexShuttle() {
          @Override public RexNode visitInputRef(RexInputRef inputRef) {
            int pos = mapping.getTargetOpt(inputRef.getIndex());
            if (pos != -1) {
              // Found it
              return rexBuilder.makeInputRef(inputRef.getType(), pos);
            }
            throw Util.FoundOne.NULL;
          }
        };
    return visitor.apply(node);
  } catch (Util.FoundOne ex) {
    Util.swallow(ex, null);
    return null;
  }
}
 
Example #10
Source File: AbstractMaterializedViewRule.java    From Bats with Apache License 2.0 6 votes vote down vote up
/**
 * Replaces all the input references by the position in the
 * input column set. If a reference index cannot be found in
 * the input set, then we return null.
 */
private static RexNode shuttleReferences(final RexBuilder rexBuilder, final RexNode node, final Mapping mapping) {
    try {
        RexShuttle visitor = new RexShuttle() {
            @Override
            public RexNode visitInputRef(RexInputRef inputRef) {
                int pos = mapping.getTargetOpt(inputRef.getIndex());
                if (pos != -1) {
                    // Found it
                    return rexBuilder.makeInputRef(inputRef.getType(), pos);
                }
                throw Util.FoundOne.NULL;
            }
        };
        return visitor.apply(node);
    } catch (Util.FoundOne ex) {
        Util.swallow(ex, null);
        return null;
    }
}
 
Example #11
Source File: FilterTableScanRule.java    From calcite with Apache License 2.0 6 votes vote down vote up
protected void apply(RelOptRuleCall call, Filter filter, TableScan scan) {
  final ImmutableIntList projects;
  final ImmutableList.Builder<RexNode> filters = ImmutableList.builder();
  if (scan instanceof Bindables.BindableTableScan) {
    final Bindables.BindableTableScan bindableScan =
        (Bindables.BindableTableScan) scan;
    filters.addAll(bindableScan.filters);
    projects = bindableScan.projects;
  } else {
    projects = scan.identity();
  }

  final Mapping mapping = Mappings.target(projects,
      scan.getTable().getRowType().getFieldCount());
  filters.add(
      RexUtil.apply(mapping.inverse(), filter.getCondition()));

  call.transformTo(
      Bindables.BindableTableScan.create(scan.getCluster(), scan.getTable(),
          filters.build(), projects));
}
 
Example #12
Source File: RelMdPredicates.java    From Bats with Apache License 2.0 6 votes vote down vote up
private void infer(RexNode predicates, Set<RexNode> allExprs,
    List<RexNode> inferredPredicates, boolean includeEqualityInference,
    ImmutableBitSet inferringFields) {
  for (RexNode r : RelOptUtil.conjunctions(predicates)) {
    if (!includeEqualityInference
        && equalityPredicates.contains(r)) {
      continue;
    }
    for (Mapping m : mappings(r)) {
      RexNode tr = r.accept(
          new RexPermuteInputsShuttle(m, joinRel.getInput(0),
              joinRel.getInput(1)));
      // Filter predicates can be already simplified, so we should work with
      // simplified RexNode versions as well. It also allows prevent of having
      // some duplicates in in result pulledUpPredicates
      RexNode simplifiedTarget =
          simplify.simplifyFilterPredicates(RelOptUtil.conjunctions(tr));
      if (checkTarget(inferringFields, allExprs, tr)
          && checkTarget(inferringFields, allExprs, simplifiedTarget)) {
        inferredPredicates.add(simplifiedTarget);
        allExprs.add(simplifiedTarget);
      }
    }
  }
}
 
Example #13
Source File: RelMdPredicates.java    From calcite with Apache License 2.0 5 votes vote down vote up
Iterable<Mapping> mappings(final RexNode predicate) {
  final ImmutableBitSet fields = exprFields.get(predicate);
  if (fields.cardinality() == 0) {
    return Collections.emptyList();
  }
  return () -> new ExprsItr(fields);
}
 
Example #14
Source File: RelMdPredicates.java    From calcite with Apache License 2.0 5 votes vote down vote up
/**
 * Infers predicates for an Aggregate.
 *
 * <p>Pulls up predicates that only contains references to columns in the
 * GroupSet. For e.g.
 *
 * <blockquote><pre>
 * inputPullUpExprs : { a &gt; 7, b + c &lt; 10, a + e = 9}
 * groupSet         : { a, b}
 * pulledUpExprs    : { a &gt; 7}
 * </pre></blockquote>
 */
public RelOptPredicateList getPredicates(Aggregate agg, RelMetadataQuery mq) {
  final RelNode input = agg.getInput();
  final RexBuilder rexBuilder = agg.getCluster().getRexBuilder();
  final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);
  final List<RexNode> aggPullUpPredicates = new ArrayList<>();

  ImmutableBitSet groupKeys = agg.getGroupSet();
  if (groupKeys.isEmpty()) {
    // "GROUP BY ()" can convert an empty relation to a non-empty relation, so
    // it is not valid to pull up predicates. In particular, consider the
    // predicate "false": it is valid on all input rows (trivially - there are
    // no rows!) but not on the output (there is one row).
    return RelOptPredicateList.EMPTY;
  }
  Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION,
      input.getRowType().getFieldCount(), agg.getRowType().getFieldCount());

  int i = 0;
  for (int j : groupKeys) {
    m.set(j, i++);
  }

  for (RexNode r : inputInfo.pulledUpPredicates) {
    ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r);
    if (groupKeys.contains(rCols)) {
      r = r.accept(new RexPermuteInputsShuttle(m, input));
      aggPullUpPredicates.add(r);
    }
  }
  return RelOptPredicateList.of(rexBuilder, aggPullUpPredicates);
}
 
Example #15
Source File: RelFieldTrimmer.java    From calcite with Apache License 2.0 5 votes vote down vote up
public TrimResult trimFields(
    Exchange exchange,
    ImmutableBitSet fieldsUsed,
    Set<RelDataTypeField> extraFields) {
  final RelDataType rowType = exchange.getRowType();
  final int fieldCount = rowType.getFieldCount();
  final RelDistribution distribution = exchange.getDistribution();
  final RelNode input = exchange.getInput();

  // We use the fields used by the consumer, plus any fields used as exchange
  // keys.
  final ImmutableBitSet.Builder inputFieldsUsed = fieldsUsed.rebuild();
  for (int keyIndex : distribution.getKeys()) {
    inputFieldsUsed.set(keyIndex);
  }

  // Create input with trimmed columns.
  final Set<RelDataTypeField> inputExtraFields = Collections.emptySet();
  final TrimResult trimResult =
      trimChild(exchange, input, inputFieldsUsed.build(), inputExtraFields);
  final 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
      && inputMapping.isIdentity()
      && fieldsUsed.cardinality() == fieldCount) {
    return result(exchange, Mappings.createIdentity(fieldCount));
  }

  relBuilder.push(newInput);
  final RelDistribution newDistribution = distribution.apply(inputMapping);
  relBuilder.exchange(newDistribution);

  return result(relBuilder.build(), inputMapping);
}
 
Example #16
Source File: MutableRels.java    From calcite with Apache License 2.0 5 votes vote down vote up
/** Equivalent to
 * {@link RelOptUtil#createProject(org.apache.calcite.rel.RelNode, java.util.List)}
 * for {@link MutableRel}. */
public static MutableRel createProject(final MutableRel child,
    final List<Integer> posList) {
  final RelDataType rowType = child.rowType;
  if (Mappings.isIdentity(posList, rowType.getFieldCount())) {
    return child;
  }
  final Mapping mapping =
      Mappings.create(
          MappingType.INVERSE_SURJECTION,
          rowType.getFieldCount(),
          posList.size());
  for (int i = 0; i < posList.size(); i++) {
    mapping.set(posList.get(i), i);
  }
  return MutableProject.of(
      RelOptUtil.permute(child.cluster.getTypeFactory(), rowType, mapping),
      child,
      new AbstractList<RexNode>() {
        public int size() {
          return posList.size();
        }

        public RexNode get(int index) {
          final int pos = posList.get(index);
          return RexInputRef.of(pos, rowType);
        }
      });
}
 
Example #17
Source File: ExtendedAggregateExtractProjectRule.java    From flink with Apache License 2.0 5 votes vote down vote up
private RelNode getNewAggregate(Aggregate oldAggregate, RelBuilder relBuilder, Mapping mapping) {

		final ImmutableBitSet newGroupSet =
			Mappings.apply(mapping, oldAggregate.getGroupSet());

		final Iterable<ImmutableBitSet> newGroupSets =
			oldAggregate.getGroupSets().stream()
				.map(bitSet -> Mappings.apply(mapping, bitSet))
				.collect(Collectors.toList());

		final List<RelBuilder.AggCall> newAggCallList =
			getNewAggCallList(oldAggregate, relBuilder, mapping);

		final RelBuilder.GroupKey groupKey =
			relBuilder.groupKey(newGroupSet, newGroupSets);

		if (oldAggregate instanceof LogicalWindowAggregate) {
			if (newGroupSet.size() == 0 && newAggCallList.size() == 0) {
				// Return the old LogicalWindowAggregate directly, as we can't get an empty Aggregate
				// from the relBuilder.
				return oldAggregate;
			} else {
				relBuilder.aggregate(groupKey, newAggCallList);
				Aggregate newAggregate = (Aggregate) relBuilder.build();
				LogicalWindowAggregate oldLogicalWindowAggregate = (LogicalWindowAggregate) oldAggregate;

				return LogicalWindowAggregate.create(
					oldLogicalWindowAggregate.getWindow(),
					oldLogicalWindowAggregate.getNamedProperties(),
					newAggregate);
			}
		} else {
			relBuilder.aggregate(groupKey, newAggCallList);
			return relBuilder.build();
		}
	}
 
Example #18
Source File: ExtendedAggregateExtractProjectRule.java    From flink with Apache License 2.0 5 votes vote down vote up
/**
 * Extract projects from the Aggregate and return the index mapping between the new projects
 * and it's input.
 */
private Mapping extractProjectsAndMapping(
	Aggregate aggregate,
	RelNode input,
	RelBuilder relBuilder) {

	// Compute which input fields are used.
	final ImmutableBitSet.Builder inputFieldsUsed = getInputFieldUsed(aggregate, input);

	final List<RexNode> projects = new ArrayList<>();
	final Mapping mapping =
		Mappings.create(MappingType.INVERSE_SURJECTION,
			aggregate.getInput().getRowType().getFieldCount(),
			inputFieldsUsed.cardinality());
	int j = 0;
	for (int i : inputFieldsUsed.build()) {
		projects.add(relBuilder.field(i));
		mapping.set(i, j++);
	}

	if (input instanceof Project) {
		// this will not create trivial projects
		relBuilder.project(projects);
	} else {
		relBuilder.project(projects, Collections.emptyList(), true);
	}

	return mapping;
}
 
Example #19
Source File: RelDistributions.java    From calcite with Apache License 2.0 5 votes vote down vote up
public RelDistribution apply(Mappings.TargetMapping mapping) {
  if (keys.isEmpty()) {
    return this;
  }
  for (int key : keys) {
    if (mapping.getTargetOpt(key) == -1) {
      return ANY; // Some distribution keys are not mapped => any.
    }
  }
  List<Integer> mappedKeys0 = Mappings.apply2((Mapping) mapping, keys);
  ImmutableIntList mappedKeys = normalizeKeys(mappedKeys0);
  return of(type, mappedKeys);
}
 
Example #20
Source File: DremioFieldTrimmer.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
/**
 * Variant of {@link #trimFields(RelNode, ImmutableBitSet, Set)} for {@link ScanCrel}.
 */
@SuppressWarnings("unused")
public TrimResult trimFields(
    ScanCrel crel,
    ImmutableBitSet fieldsUsed,
    Set<RelDataTypeField> extraFields) {

  if(fieldsUsed.cardinality() == crel.getRowType().getFieldCount()) {
    return result(crel, Mappings.createIdentity(crel.getRowType().getFieldCount()));
  }

  if(fieldsUsed.cardinality() == 0) {
    // do something similar to dummy project but avoid using a scan field. This ensures the scan
    // does a skipAll operation rather than projectin a useless column.
    final RelOptCluster cluster = crel.getCluster();
    final Mapping mapping = Mappings.create(MappingType.INVERSE_SURJECTION, crel.getRowType().getFieldCount(), 1);
    final RexLiteral expr = cluster.getRexBuilder().makeExactLiteral(BigDecimal.ZERO);
    builder.push(crel);
    builder.project(ImmutableList.<RexNode>of(expr), ImmutableList.of("DUMMY"));
    return result(builder.build(), mapping);
  }

  final List<SchemaPath> paths = new ArrayList<>();
  final Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION, crel.getRowType().getFieldCount(), fieldsUsed.cardinality());
  int index = 0;
  for(int i : fieldsUsed) {
    paths.add(SchemaPath.getSimplePath(crel.getRowType().getFieldList().get(i).getName()));
    m.set(i, index);
    index++;
  }

  ScanCrel newCrel = crel.cloneWithProject(paths);
  return result(newCrel, m);
}
 
Example #21
Source File: DremioFieldTrimmer.java    From dremio-oss with Apache License 2.0 5 votes vote down vote up
@Override
protected TrimResult result(RelNode r, final Mapping mapping) {
  final RexBuilder rexBuilder = builder.getRexBuilder();
  for (final CorrelationId correlation : r.getVariablesSet()) {
    r = r.accept(
            new CorrelationReferenceFinder() {
              protected RexNode handle(RexFieldAccess fieldAccess) {
                final RexCorrelVariable v =
                        (RexCorrelVariable) fieldAccess.getReferenceExpr();
                if (v.id.equals(correlation)) {
                  final int old = fieldAccess.getField().getIndex();
                  final int new_ = mapping.getTarget(old);
                  final RelDataTypeFactory.Builder typeBuilder =
                          builder.getTypeFactory().builder();
                  for (IntPair pair : mapping) {
                    if (pair.source < v.getType().getFieldCount()) {
                      typeBuilder.add(v.getType().getFieldList().get(pair.source));
                    }
                  }
                  final RexNode newV =
                          rexBuilder.makeCorrel(typeBuilder.build(), v.id);
                  if (old != new_) {
                    return rexBuilder.makeFieldAccess(newV, new_);
                  }
                }
                return fieldAccess;
              }
            });
  }
  return new TrimResult(r, mapping);
}
 
Example #22
Source File: RelFieldTrimmer.java    From calcite with Apache License 2.0 5 votes vote down vote up
protected Mapping createMapping(ImmutableBitSet fieldsUsed, int fieldCount) {
  final Mapping mapping =
      Mappings.create(
          MappingType.INVERSE_SURJECTION,
          fieldCount,
          fieldsUsed.cardinality());
  int i = 0;
  for (int field : fieldsUsed) {
    mapping.set(field, i++);
  }
  return mapping;
}
 
Example #23
Source File: RelFieldTrimmer.java    From calcite with Apache License 2.0 5 votes vote down vote up
protected TrimResult result(RelNode r, final Mapping mapping) {
  final RexBuilder rexBuilder = relBuilder.getRexBuilder();
  for (final CorrelationId correlation : r.getVariablesSet()) {
    r = r.accept(
        new CorrelationReferenceFinder() {
          protected RexNode handle(RexFieldAccess fieldAccess) {
            final RexCorrelVariable v =
                (RexCorrelVariable) fieldAccess.getReferenceExpr();
            if (v.id.equals(correlation)
                && v.getType().getFieldCount() == mapping.getSourceCount()) {
              final int old = fieldAccess.getField().getIndex();
              final int new_ = mapping.getTarget(old);
              final RelDataTypeFactory.Builder typeBuilder =
                  relBuilder.getTypeFactory().builder();
              for (int target : Util.range(mapping.getTargetCount())) {
                typeBuilder.add(
                    v.getType().getFieldList().get(mapping.getSource(target)));
              }
              final RexNode newV =
                  rexBuilder.makeCorrel(typeBuilder.build(), v.id);
              if (old != new_) {
                return rexBuilder.makeFieldAccess(newV, new_);
              }
            }
            return fieldAccess;
          }
        });
  }
  return new TrimResult(r, mapping);
}
 
Example #24
Source File: ExtendedAggregateExtractProjectRule.java    From flink with Apache License 2.0 5 votes vote down vote up
private RelNode getNewAggregate(Aggregate oldAggregate, RelBuilder relBuilder, Mapping mapping) {

		final ImmutableBitSet newGroupSet =
			Mappings.apply(mapping, oldAggregate.getGroupSet());

		final Iterable<ImmutableBitSet> newGroupSets =
			oldAggregate.getGroupSets().stream()
				.map(bitSet -> Mappings.apply(mapping, bitSet))
				.collect(Collectors.toList());

		final List<RelBuilder.AggCall> newAggCallList =
			getNewAggCallList(oldAggregate, relBuilder, mapping);

		final RelBuilder.GroupKey groupKey =
			relBuilder.groupKey(newGroupSet, newGroupSets);

		if (oldAggregate instanceof LogicalWindowAggregate) {
			if (newGroupSet.size() == 0 && newAggCallList.size() == 0) {
				// Return the old LogicalWindowAggregate directly, as we can't get an empty Aggregate
				// from the relBuilder.
				return oldAggregate;
			} else {
				relBuilder.aggregate(groupKey, newAggCallList);
				Aggregate newAggregate = (Aggregate) relBuilder.build();
				LogicalWindowAggregate oldLogicalWindowAggregate = (LogicalWindowAggregate) oldAggregate;

				return LogicalWindowAggregate.create(
					oldLogicalWindowAggregate.getWindow(),
					oldLogicalWindowAggregate.getNamedProperties(),
					newAggregate);
			}
		} else {
			relBuilder.aggregate(groupKey, newAggCallList);
			return relBuilder.build();
		}
	}
 
Example #25
Source File: RelMdPredicates.java    From Bats with Apache License 2.0 5 votes vote down vote up
/**
 * Infers predicates for an Aggregate.
 *
 * <p>Pulls up predicates that only contains references to columns in the
 * GroupSet. For e.g.
 *
 * <blockquote><pre>
 * inputPullUpExprs : { a &gt; 7, b + c &lt; 10, a + e = 9}
 * groupSet         : { a, b}
 * pulledUpExprs    : { a &gt; 7}
 * </pre></blockquote>
 */
public RelOptPredicateList getPredicates(Aggregate agg, RelMetadataQuery mq) {
  final RelNode input = agg.getInput();
  final RexBuilder rexBuilder = agg.getCluster().getRexBuilder();
  final RelOptPredicateList inputInfo = mq.getPulledUpPredicates(input);
  final List<RexNode> aggPullUpPredicates = new ArrayList<>();

  ImmutableBitSet groupKeys = agg.getGroupSet();
  if (groupKeys.isEmpty()) {
    // "GROUP BY ()" can convert an empty relation to a non-empty relation, so
    // it is not valid to pull up predicates. In particular, consider the
    // predicate "false": it is valid on all input rows (trivially - there are
    // no rows!) but not on the output (there is one row).
    return RelOptPredicateList.EMPTY;
  }
  Mapping m = Mappings.create(MappingType.PARTIAL_FUNCTION,
      input.getRowType().getFieldCount(), agg.getRowType().getFieldCount());

  int i = 0;
  for (int j : groupKeys) {
    m.set(j, i++);
  }

  for (RexNode r : inputInfo.pulledUpPredicates) {
    ImmutableBitSet rCols = RelOptUtil.InputFinder.bits(r);
    if (groupKeys.contains(rCols)) {
      r = r.accept(new RexPermuteInputsShuttle(m, input));
      aggPullUpPredicates.add(r);
    }
  }
  return RelOptPredicateList.of(rexBuilder, aggPullUpPredicates);
}
 
Example #26
Source File: RelMdPredicates.java    From Bats with Apache License 2.0 5 votes vote down vote up
Iterable<Mapping> mappings(final RexNode predicate) {
  final ImmutableBitSet fields = exprFields.get(predicate);
  if (fields.cardinality() == 0) {
    return Collections.emptyList();
  }
  return () -> new ExprsItr(fields);
}
 
Example #27
Source File: RelDistributions.java    From Bats with Apache License 2.0 5 votes vote down vote up
public RelDistribution apply(Mappings.TargetMapping mapping) {
  if (keys.isEmpty()) {
    return this;
  }
  return getTraitDef().canonize(
      new RelDistributionImpl(type,
          ImmutableIntList.copyOf(
              Mappings.apply((Mapping) mapping, keys))));
}
 
Example #28
Source File: RelFieldTrimmer.java    From Bats with Apache License 2.0 5 votes vote down vote up
/** Creates a project with a dummy column, to protect the parts of the system
 * that cannot handle a relational expression with no columns.
 *
 * @param fieldCount Number of fields in the original relational expression
 * @param input Trimmed input
 * @return Dummy project, or null if no dummy is required
 */
protected TrimResult dummyProject(int fieldCount, RelNode input) {
    final RelOptCluster cluster = input.getCluster();
    final Mapping mapping = Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, 1);
    if (input.getRowType().getFieldCount() == 1) {
        // Input already has one field (and may in fact be a dummy project we
        // created for the child). We can't do better.
        return result(input, mapping);
    }
    final RexLiteral expr = cluster.getRexBuilder().makeExactLiteral(BigDecimal.ZERO);
    relBuilder.push(input);
    relBuilder.project(ImmutableList.<RexNode> of(expr), ImmutableList.of("DUMMY"));
    return result(relBuilder.build(), mapping);
}
 
Example #29
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 #30
Source File: RelFieldTrimmer.java    From Bats with Apache License 2.0 5 votes vote down vote up
protected Mapping createMapping(ImmutableBitSet fieldsUsed, int fieldCount) {
    final Mapping mapping = Mappings.create(MappingType.INVERSE_SURJECTION, fieldCount, fieldsUsed.cardinality());
    int i = 0;
    for (int field : fieldsUsed) {
        mapping.set(field, i++);
    }
    return mapping;
}