com.hazelcast.org.apache.calcite.rel.core.Sort Maven / Gradle / Ivy
/*
* 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 com.hazelcast.org.apache.calcite.rel.core;
import com.hazelcast.org.apache.calcite.linq4j.Ord;
import com.hazelcast.org.apache.calcite.plan.RelOptCluster;
import com.hazelcast.org.apache.calcite.plan.RelOptCost;
import com.hazelcast.org.apache.calcite.plan.RelOptPlanner;
import com.hazelcast.org.apache.calcite.plan.RelTraitSet;
import com.hazelcast.org.apache.calcite.rel.RelCollation;
import com.hazelcast.org.apache.calcite.rel.RelCollationTraitDef;
import com.hazelcast.org.apache.calcite.rel.RelFieldCollation;
import com.hazelcast.org.apache.calcite.rel.RelInput;
import com.hazelcast.org.apache.calcite.rel.RelNode;
import com.hazelcast.org.apache.calcite.rel.RelWriter;
import com.hazelcast.org.apache.calcite.rel.SingleRel;
import com.hazelcast.org.apache.calcite.rel.metadata.RelMetadataQuery;
import com.hazelcast.org.apache.calcite.rex.RexNode;
import com.hazelcast.org.apache.calcite.rex.RexShuttle;
import com.hazelcast.org.apache.calcite.util.Util;
import com.hazelcast.com.google.common.collect.ImmutableList;
import java.util.Collections;
import java.util.List;
/**
* Relational expression that imposes a particular sort order on its input
* without otherwise changing its content.
*/
public abstract class Sort extends SingleRel {
//~ Instance fields --------------------------------------------------------
public final RelCollation collation;
protected final ImmutableList fieldExps;
public final RexNode offset;
public final RexNode fetch;
//~ Constructors -----------------------------------------------------------
/**
* Creates a Sort.
*
* @param cluster Cluster this relational expression belongs to
* @param traits Traits
* @param child input relational expression
* @param collation array of sort specifications
*/
public Sort(
RelOptCluster cluster,
RelTraitSet traits,
RelNode child,
RelCollation collation) {
this(cluster, traits, child, collation, null, null);
}
/**
* Creates a Sort.
*
* @param cluster Cluster this relational expression belongs to
* @param traits Traits
* @param child input relational expression
* @param collation array of sort specifications
* @param offset Expression for number of rows to discard before returning
* first row
* @param fetch Expression for number of rows to fetch
*/
public Sort(
RelOptCluster cluster,
RelTraitSet traits,
RelNode child,
RelCollation collation,
RexNode offset,
RexNode fetch) {
super(cluster, traits, child);
this.collation = collation;
this.offset = offset;
this.fetch = fetch;
assert traits.containsIfApplicable(collation)
: "traits=" + traits + ", collation=" + collation;
assert !(fetch == null
&& offset == null
&& collation.getFieldCollations().isEmpty())
: "trivial sort";
ImmutableList.Builder builder = ImmutableList.builder();
for (RelFieldCollation field : collation.getFieldCollations()) {
int index = field.getFieldIndex();
builder.add(cluster.getRexBuilder().makeInputRef(child, index));
}
fieldExps = builder.build();
}
/**
* Creates a Sort by parsing serialized output.
*/
public Sort(RelInput input) {
this(input.getCluster(), input.getTraitSet().plus(input.getCollation()),
input.getInput(),
RelCollationTraitDef.INSTANCE.canonize(input.getCollation()),
input.getExpression("offset"), input.getExpression("fetch"));
}
//~ Methods ----------------------------------------------------------------
@Override public final Sort copy(RelTraitSet traitSet, List inputs) {
return copy(traitSet, sole(inputs), collation, offset, fetch);
}
public final Sort copy(RelTraitSet traitSet, RelNode newInput,
RelCollation newCollation) {
return copy(traitSet, newInput, newCollation, offset, fetch);
}
public abstract Sort copy(RelTraitSet traitSet, RelNode newInput,
RelCollation newCollation, RexNode offset, RexNode fetch);
@Override public RelOptCost computeSelfCost(RelOptPlanner planner,
RelMetadataQuery mq) {
// Higher cost if rows are wider discourages pushing a project through a
// sort.
final double rowCount = mq.getRowCount(this);
final double bytesPerRow = getRowType().getFieldCount() * 4;
final double cpu = Util.nLogN(rowCount) * bytesPerRow;
return planner.getCostFactory().makeCost(rowCount, cpu, 0);
}
@Override public List getChildExps() {
return fieldExps;
}
public RelNode accept(RexShuttle shuttle) {
RexNode offset = shuttle.apply(this.offset);
RexNode fetch = shuttle.apply(this.fetch);
List fieldExps = shuttle.apply(this.fieldExps);
assert fieldExps == this.fieldExps
: "Sort node does not support modification of input field expressions."
+ " Old expressions: " + this.fieldExps + ", new ones: " + fieldExps;
if (offset == this.offset
&& fetch == this.fetch) {
return this;
}
return copy(traitSet, getInput(), collation, offset, fetch);
}
@Override public boolean isEnforcer() {
return offset == null && fetch == null
&& collation.getFieldCollations().size() > 0;
}
/**
* Returns the array of {@link RelFieldCollation}s asked for by the sort
* specification, from most significant to least significant.
*
* See also {@link RelMetadataQuery#collations(RelNode)},
* which lists all known collations. For example,
* ORDER BY time_id
might also be sorted by
* the_year, the_month
because of a known monotonicity
* constraint among the columns. {@code getCollation} would return
* [time_id]
and {@code collations} would return
* [ [time_id], [the_year, the_month] ]
.
*/
public RelCollation getCollation() {
return collation;
}
@SuppressWarnings("deprecation")
@Override public List getCollationList() {
return Collections.singletonList(getCollation());
}
public RelWriter explainTerms(RelWriter pw) {
super.explainTerms(pw);
assert fieldExps.size() == collation.getFieldCollations().size();
if (pw.nest()) {
pw.item("collation", collation);
} else {
for (Ord ord : Ord.zip(fieldExps)) {
pw.item("sort" + ord.i, ord.e);
}
for (Ord ord
: Ord.zip(collation.getFieldCollations())) {
pw.item("dir" + ord.i, ord.e.shortString());
}
}
pw.itemIf("offset", offset, offset != null);
pw.itemIf("fetch", fetch, fetch != null);
return pw;
}
}