use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.RelCollation in project calcite by apache.
the class EnumerableMergeJoinRule method convert.
@Override
public RelNode convert(RelNode rel) {
LogicalJoin join = (LogicalJoin) rel;
final JoinInfo info = JoinInfo.of(join.getLeft(), join.getRight(), join.getCondition());
if (join.getJoinType() != JoinRelType.INNER) {
// (It supports non-equi join, using a post-filter; see below.)
return null;
}
if (info.pairs().size() == 0) {
// EnumerableMergeJoin CAN support cartesian join, but disable it for now.
return null;
}
final List<RelNode> newInputs = Lists.newArrayList();
final List<RelCollation> collations = Lists.newArrayList();
int offset = 0;
for (Ord<RelNode> ord : Ord.zip(join.getInputs())) {
RelTraitSet traits = ord.e.getTraitSet().replace(EnumerableConvention.INSTANCE);
if (!info.pairs().isEmpty()) {
final List<RelFieldCollation> fieldCollations = Lists.newArrayList();
for (int key : info.keys().get(ord.i)) {
fieldCollations.add(new RelFieldCollation(key, RelFieldCollation.Direction.ASCENDING, RelFieldCollation.NullDirection.LAST));
}
final RelCollation collation = RelCollations.of(fieldCollations);
collations.add(RelCollations.shift(collation, offset));
traits = traits.replace(collation);
}
newInputs.add(convert(ord.e, traits));
offset += ord.e.getRowType().getFieldCount();
}
final RelNode left = newInputs.get(0);
final RelNode right = newInputs.get(1);
final RelOptCluster cluster = join.getCluster();
RelNode newRel;
try {
RelTraitSet traits = join.getTraitSet().replace(EnumerableConvention.INSTANCE);
if (!collations.isEmpty()) {
traits = traits.replace(collations);
}
newRel = new EnumerableMergeJoin(cluster, traits, left, right, info.getEquiCondition(left, right, cluster.getRexBuilder()), info.leftKeys, info.rightKeys, join.getVariablesSet(), join.getJoinType());
} catch (InvalidRelException e) {
EnumerableRules.LOGGER.debug(e.toString());
return null;
}
if (!info.isEqui()) {
newRel = new EnumerableFilter(cluster, newRel.getTraitSet(), newRel, info.getRemaining(cluster.getRexBuilder()));
}
return newRel;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.RelCollation in project calcite by apache.
the class CloneSchema method createCloneTable.
public static <T> Table createCloneTable(final JavaTypeFactory typeFactory, final RelProtoDataType protoRowType, final List<RelCollation> collations, final List<ColumnMetaData.Rep> repList, final Enumerable<T> source) {
final Type elementType;
if (source instanceof QueryableTable) {
elementType = ((QueryableTable) source).getElementType();
} else if (protoRowType.apply(typeFactory).getFieldCount() == 1) {
if (repList != null) {
elementType = repList.get(0).clazz;
} else {
elementType = Object.class;
}
} else {
elementType = Object[].class;
}
return new ArrayTable(elementType, protoRowType, Suppliers.memoize(new Supplier<ArrayTable.Content>() {
public ArrayTable.Content get() {
final ColumnLoader loader = new ColumnLoader<>(typeFactory, source, protoRowType, repList);
final List<RelCollation> collation2 = collations.isEmpty() && loader.sortField >= 0 ? RelCollations.createSingleton(loader.sortField) : collations;
return new ArrayTable.Content(loader.representationValues, loader.size(), collation2);
}
}));
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.RelCollation in project calcite by apache.
the class RelMdUtil method checkInputForCollationAndLimit.
/**
* Returns whether a relational expression is already sorted and has fewer
* rows than the sum of offset and limit.
*
* <p>If this is the case, it is safe to push down a
* {@link org.apache.calcite.rel.core.Sort} with limit and optional offset.
*/
public static boolean checkInputForCollationAndLimit(RelMetadataQuery mq, RelNode input, RelCollation collation, RexNode offset, RexNode fetch) {
// Check if the input is already sorted
boolean alreadySorted = collation.getFieldCollations().isEmpty();
for (RelCollation inputCollation : mq.collations(input)) {
if (inputCollation.satisfies(collation)) {
alreadySorted = true;
break;
}
}
// Check if we are not reducing the number of tuples
boolean alreadySmaller = true;
final Double rowCount = mq.getMaxRowCount(input);
if (rowCount != null && fetch != null) {
final int offsetVal = offset == null ? 0 : RexLiteral.intValue(offset);
final int limit = RexLiteral.intValue(fetch);
if ((double) offsetVal + (double) limit < rowCount) {
alreadySmaller = false;
}
}
return alreadySorted && alreadySmaller;
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.RelCollation in project calcite by apache.
the class RelMdCollation method mergeJoin.
/**
* Helper method to determine a {@link Join}'s collation assuming that it
* uses a merge-join algorithm.
*
* <p>If the inputs are sorted on other keys <em>in addition to</em> the join
* key, the result preserves those collations too.
*/
public static List<RelCollation> mergeJoin(RelMetadataQuery mq, RelNode left, RelNode right, ImmutableIntList leftKeys, ImmutableIntList rightKeys) {
final ImmutableList.Builder<RelCollation> builder = ImmutableList.builder();
final ImmutableList<RelCollation> leftCollations = mq.collations(left);
assert RelCollations.contains(leftCollations, leftKeys) : "cannot merge join: left input is not sorted on left keys";
builder.addAll(leftCollations);
final ImmutableList<RelCollation> rightCollations = mq.collations(right);
assert RelCollations.contains(rightCollations, rightKeys) : "cannot merge join: right input is not sorted on right keys";
final int leftFieldCount = left.getRowType().getFieldCount();
for (RelCollation collation : rightCollations) {
builder.add(RelCollations.shift(collation, leftFieldCount));
}
return builder.build();
}
use of org.apache.beam.vendor.calcite.v1_28_0.org.apache.calcite.rel.RelCollation in project calcite by apache.
the class RelMdCollation method project.
/**
* Helper method to determine a {@link Project}'s collation.
*/
public static List<RelCollation> project(RelMetadataQuery mq, RelNode input, List<? extends RexNode> projects) {
final SortedSet<RelCollation> collations = new TreeSet<>();
final List<RelCollation> inputCollations = mq.collations(input);
if (inputCollations == null || inputCollations.isEmpty()) {
return ImmutableList.of();
}
final Multimap<Integer, Integer> targets = LinkedListMultimap.create();
final Map<Integer, SqlMonotonicity> targetsWithMonotonicity = new HashMap<>();
for (Ord<RexNode> project : Ord.<RexNode>zip(projects)) {
if (project.e instanceof RexInputRef) {
targets.put(((RexInputRef) project.e).getIndex(), project.i);
} else if (project.e instanceof RexCall) {
final RexCall call = (RexCall) project.e;
final RexCallBinding binding = RexCallBinding.create(input.getCluster().getTypeFactory(), call, inputCollations);
targetsWithMonotonicity.put(project.i, call.getOperator().getMonotonicity(binding));
}
}
final List<RelFieldCollation> fieldCollations = new ArrayList<>();
loop: for (RelCollation ic : inputCollations) {
if (ic.getFieldCollations().isEmpty()) {
continue;
}
fieldCollations.clear();
for (RelFieldCollation ifc : ic.getFieldCollations()) {
final Collection<Integer> integers = targets.get(ifc.getFieldIndex());
if (integers.isEmpty()) {
// cannot do this collation
continue loop;
}
fieldCollations.add(ifc.copy(integers.iterator().next()));
}
assert !fieldCollations.isEmpty();
collations.add(RelCollations.of(fieldCollations));
}
final List<RelFieldCollation> fieldCollationsForRexCalls = new ArrayList<>();
for (Map.Entry<Integer, SqlMonotonicity> entry : targetsWithMonotonicity.entrySet()) {
final SqlMonotonicity value = entry.getValue();
switch(value) {
case NOT_MONOTONIC:
case CONSTANT:
break;
default:
fieldCollationsForRexCalls.add(new RelFieldCollation(entry.getKey(), RelFieldCollation.Direction.of(value)));
break;
}
}
if (!fieldCollationsForRexCalls.isEmpty()) {
collations.add(RelCollations.of(fieldCollationsForRexCalls));
}
return ImmutableList.copyOf(collations);
}
Aggregations