/**
* 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.hadoop.hive.ql.optimizer.calcite;
import org.apache.calcite.plan.Context;
import org.apache.calcite.plan.Contexts;
import org.apache.calcite.plan.RelOptCluster;
import org.apache.calcite.plan.RelOptSchema;
import org.apache.calcite.rel.RelCollations;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rex.RexNode;
import org.apache.calcite.rex.RexUtil;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.server.CalciteServerStatement;
import org.apache.calcite.tools.FrameworkConfig;
import org.apache.calcite.tools.Frameworks;
import org.apache.calcite.tools.RelBuilder;
import org.apache.calcite.tools.RelBuilderFactory;
/**
* Builder for relational expressions in Hive.
*
* <p>{@code RelBuilder} does not make possible anything that you could not
* also accomplish by calling the factory methods of the particular relational
* expression. But it makes common tasks more straightforward and concise.
*
* <p>It is not thread-safe.
*/
public class HiveRelBuilder extends RelBuilder {
private HiveRelBuilder(Context context, RelOptCluster cluster, RelOptSchema relOptSchema) {
super(context, cluster, relOptSchema);
}
/** Creates a RelBuilder. */
public static RelBuilder create(FrameworkConfig config) {
final RelOptCluster[] clusters = {null};
final RelOptSchema[] relOptSchemas = {null};
Frameworks.withPrepare(
new Frameworks.PrepareAction<Void>(config) {
public Void apply(RelOptCluster cluster, RelOptSchema relOptSchema,
SchemaPlus rootSchema, CalciteServerStatement statement) {
clusters[0] = cluster;
relOptSchemas[0] = relOptSchema;
return null;
}
});
return new HiveRelBuilder(config.getContext(), clusters[0], relOptSchemas[0]);
}
/** Creates a {@link RelBuilderFactory}, a partially-created RelBuilder.
* Just add a {@link RelOptCluster} and a {@link RelOptSchema} */
public static RelBuilderFactory proto(final Context context) {
return new RelBuilderFactory() {
public RelBuilder create(RelOptCluster cluster, RelOptSchema schema) {
return new HiveRelBuilder(context, cluster, schema);
}
};
}
/** Creates a {@link RelBuilderFactory} that uses a given set of factories. */
public static RelBuilderFactory proto(Object... factories) {
return proto(Contexts.of(factories));
}
@Override
public RelBuilder filter(Iterable<? extends RexNode> predicates) {
final RexNode x = RexUtil.simplify(cluster.getRexBuilder(),
RexUtil.composeConjunction(cluster.getRexBuilder(), predicates, false));
if (!x.isAlwaysTrue()) {
final RelNode input = build();
final RelNode filter = HiveRelFactories.HIVE_FILTER_FACTORY.createFilter(input, x);
return this.push(filter);
}
return this;
}
/**
* Empty relationship can be expressed in many different ways, e.g.,
* filter(cond=false), empty LogicalValues(), etc. Calcite default implementation
* uses empty LogicalValues(); however, currently there is not an equivalent to
* this expression in Hive. Thus, we use limit 0, since Hive already includes
* optimizations that will do early pruning of the result tree when it is found,
* e.g., GlobalLimitOptimizer.
*/
@Override
public RelBuilder empty() {
final RelNode input = build();
final RelNode sort = HiveRelFactories.HIVE_SORT_FACTORY.createSort(
input, RelCollations.of(), null, literal(0));
return this.push(sort);
}
}