blob: 19219f741a10e537c4989b41b194f31025e1e21b [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to you under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.calcite.rel;
import org.apache.calcite.plan.RelMultipleTrait;
import org.apache.calcite.plan.RelOptPlanner;
import org.apache.calcite.plan.RelTrait;
import org.apache.calcite.plan.RelTraitDef;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.runtime.Utilities;
import org.apache.calcite.util.Util;
import org.apache.calcite.util.mapping.Mappings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.UnmodifiableIterator;
import org.checkerframework.checker.nullness.qual.Nullable;
import java.util.Iterator;
import java.util.List;
import static com.google.common.base.Preconditions.checkArgument;
/**
* Simple implementation of {@link RelCollation}.
*/
public class RelCollationImpl implements RelCollation {
//~ Static fields/initializers ---------------------------------------------
@Deprecated // to be removed before 2.0
public static final RelCollation EMPTY = RelCollations.EMPTY;
@Deprecated // to be removed before 2.0
public static final RelCollation PRESERVE = RelCollations.PRESERVE;
//~ Instance fields --------------------------------------------------------
private final ImmutableList<RelFieldCollation> fieldCollations;
//~ Constructors -----------------------------------------------------------
protected RelCollationImpl(ImmutableList<RelFieldCollation> fieldCollations) {
this.fieldCollations = fieldCollations;
checkArgument(Util.isDistinct(RelCollations.ordinals(fieldCollations)),
"fields must be distinct");
}
@Deprecated // to be removed before 2.0
public static RelCollation of(RelFieldCollation... fieldCollations) {
return RelCollations.of(fieldCollations);
}
@Deprecated // to be removed before 2.0
public static RelCollation of(List<RelFieldCollation> fieldCollations) {
return RelCollations.of(fieldCollations);
}
//~ Methods ----------------------------------------------------------------
@Override public RelTraitDef getTraitDef() {
return RelCollationTraitDef.INSTANCE;
}
@Override public List<RelFieldCollation> getFieldCollations() {
return fieldCollations;
}
@Override public int hashCode() {
return fieldCollations.hashCode();
}
@Override public boolean equals(@Nullable Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof RelCollationImpl) {
RelCollationImpl that = (RelCollationImpl) obj;
return this.fieldCollations.equals(that.fieldCollations);
}
return false;
}
@Override public boolean isTop() {
return fieldCollations.isEmpty();
}
@Override public int compareTo(RelMultipleTrait o) {
final RelCollationImpl that = (RelCollationImpl) o;
final UnmodifiableIterator<RelFieldCollation> iterator =
that.fieldCollations.iterator();
for (RelFieldCollation f : fieldCollations) {
if (!iterator.hasNext()) {
return 1;
}
final RelFieldCollation f2 = iterator.next();
int c = Utilities.compare(f.getFieldIndex(), f2.getFieldIndex());
if (c != 0) {
return c;
}
}
return iterator.hasNext() ? -1 : 0;
}
@Override public void register(RelOptPlanner planner) {}
/**
* Applies mapping to a given collation.
*
* <p>If mapping destroys the collation prefix, this method returns an empty
* collation. Examples of applying mappings to collation [0, 1]:
*
* <ul>
* <li>mapping(0, 1) =&gt; [0, 1]</li>
* <li>mapping(1, 0) =&gt; [1, 0]</li>
* <li>mapping(0) =&gt; [0]</li>
* <li>mapping(1) =&gt; []</li>
* <li>mapping(2, 0) =&gt; [1]</li>
* <li>mapping(2, 1, 0) =&gt; [2, 1]</li>
* <li>mapping(2, 1) =&gt; []</li>
* </ul>
*
* @param mapping Mapping
* @return Collation with applied mapping.
*/
@Override public RelCollationImpl apply(
final Mappings.TargetMapping mapping) {
return (RelCollationImpl) RexUtil.apply(mapping, this);
}
@Override public boolean satisfies(RelTrait trait) {
return this == trait
|| trait instanceof RelCollationImpl
&& Util.startsWith(fieldCollations,
((RelCollationImpl) trait).fieldCollations);
}
/** Returns a string representation of this collation, suitably terse given
* that it will appear in plan traces. Examples:
* "[]", "[2]", "[0 DESC, 1]", "[0 DESC, 1 ASC NULLS LAST]". */
@Override public String toString() {
Iterator<RelFieldCollation> it = fieldCollations.iterator();
if (! it.hasNext()) {
return "[]";
}
StringBuilder sb = new StringBuilder();
sb.append('[');
for (;;) {
RelFieldCollation e = it.next();
sb.append(e.getFieldIndex());
if (e.direction != RelFieldCollation.Direction.ASCENDING
|| e.nullDirection != e.direction.defaultNullDirection()) {
sb.append(' ').append(e.shortString());
}
if (!it.hasNext()) {
return sb.append(']').toString();
}
sb.append(',').append(' ');
}
}
@Deprecated // to be removed before 2.0
public static List<RelCollation> createSingleton(int fieldIndex) {
return RelCollations.createSingleton(fieldIndex);
}
@Deprecated // to be removed before 2.0
public static boolean isValid(
RelDataType rowType,
List<RelCollation> collationList,
boolean fail) {
return RelCollations.isValid(rowType, collationList, fail);
}
@Deprecated // to be removed before 2.0
public static boolean equal(
List<RelCollation> collationList1,
List<RelCollation> collationList2) {
return RelCollations.equal(collationList1, collationList2);
}
@Deprecated // to be removed before 2.0
public static List<Integer> ordinals(RelCollation collation) {
return RelCollations.ordinals(collation);
}
}