org.apache.hadoop.hive.ql.optimizer.PrunerOperatorFactory Maven / Gradle / Ivy
The newest version!
/**
* 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;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import org.apache.hadoop.hive.ql.exec.FilterOperator;
import org.apache.hadoop.hive.ql.exec.TableScanOperator;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.lib.Node;
import org.apache.hadoop.hive.ql.lib.NodeProcessor;
import org.apache.hadoop.hive.ql.lib.NodeProcessorCtx;
import org.apache.hadoop.hive.ql.metadata.Partition;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.parse.TypeCheckProcFactory;
import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
/**
* Operator factory for pruning processing of operator graph We find
* all the filter operators that appear just beneath the table scan operators.
* We then pass the filter to the pruner to construct a pruner for
* that table alias and store a mapping from the table scan operator to that
* pruner. We call that pruner later during plan generation.
*
* Create this class from org.apache.hadoop.hive.ql.optimizer.ppr.OpProcFactory
* so that in addition to ppr, other pruner like list bucketin pruner can use it.
*/
public abstract class PrunerOperatorFactory {
/**
* Determines the partition pruner for the filter. This is called only when
* the filter follows a table scan operator.
*/
public static abstract class FilterPruner implements NodeProcessor {
@Override
public Object process(Node nd, Stack stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
FilterOperator fop = (FilterOperator) nd;
FilterOperator fop2 = null;
// The stack contains either ... TS, Filter or
// ... TS, Filter, Filter with the head of the stack being the rightmost
// symbol. So we just pop out the two elements from the top and if the
// second one of them is not a table scan then the operator on the top of
// the stack is the Table scan operator.
Node tmp = stack.pop();
Node tmp2 = stack.pop();
TableScanOperator top = null;
if (tmp2 instanceof TableScanOperator) {
top = (TableScanOperator) tmp2;
} else {
top = (TableScanOperator) stack.peek();
fop2 = (FilterOperator) tmp2;
}
stack.push(tmp2);
stack.push(tmp);
// If fop2 exists (i.e this is not the top level filter and fop2 is not
// a sampling filter then we ignore the current filter
if (fop2 != null && !fop2.getConf().getIsSamplingPred()) {
return null;
}
// ignore the predicate in case it is not a sampling predicate
if (fop.getConf().getIsSamplingPred()) {
return null;
}
generatePredicate(procCtx, fop, top);
return null;
}
/**
* Generate predicate.
*
* Subclass should implement the function. Please refer to {@link OpProcFactory.FilterPPR}
*
* @param procCtx
* @param fop
* @param top
* @throws SemanticException
* @throws UDFArgumentException
*/
protected abstract void generatePredicate(NodeProcessorCtx procCtx, FilterOperator fop,
TableScanOperator top) throws SemanticException, UDFArgumentException;
/**
* Add pruning predicate.
*
* @param opToPrunner
* @param top
* @param new_pruner_pred
* @throws UDFArgumentException
*/
protected void addPruningPred(Map opToPrunner,
TableScanOperator top, ExprNodeDesc new_pruner_pred) throws UDFArgumentException {
ExprNodeDesc old_pruner_pred = opToPrunner.get(top);
ExprNodeDesc pruner_pred = null;
if (old_pruner_pred != null) {
// or the old_pruner_pred and the new_ppr_pred
pruner_pred = TypeCheckProcFactory.DefaultExprProcessor.getFuncExprNodeDesc("OR",
old_pruner_pred, new_pruner_pred);
} else {
pruner_pred = new_pruner_pred;
}
// Put the mapping from table scan operator to pruner_pred
opToPrunner.put(top, pruner_pred);
return;
}
/**
* Add pruning predicate.
*
* @param opToPrunner
* @param top
* @param new_pruner_pred
* @param part
* @throws UDFArgumentException
*/
protected void addPruningPred(Map> opToPrunner,
TableScanOperator top, ExprNodeDesc new_pruner_pred, Partition part)
throws UDFArgumentException {
Map oldPartToPruner = opToPrunner.get(top);
Map partToPruner = null;
ExprNodeDesc pruner_pred = null;
if (oldPartToPruner == null) {
pruner_pred = new_pruner_pred;
// create new mapping
partToPruner = new HashMap();
} else {
partToPruner = oldPartToPruner;
ExprNodeDesc old_pruner_pred = oldPartToPruner.get(part.getName());
if (old_pruner_pred != null) {
// or the old_pruner_pred and the new_ppr_pred
pruner_pred = TypeCheckProcFactory.DefaultExprProcessor.getFuncExprNodeDesc("OR",
old_pruner_pred, new_pruner_pred);
} else {
pruner_pred = new_pruner_pred;
}
}
// Put the mapping from part to pruner_pred
partToPruner.put(part.getName(), pruner_pred);
// Put the mapping from table scan operator to part-pruner map
opToPrunner.put(top, partToPruner);
return;
}
}
/**
* Default processor which just merges its children.
*/
public static class DefaultPruner implements NodeProcessor {
@Override
public Object process(Node nd, Stack stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
// Nothing needs to be done.
return null;
}
}
/**
* Instantiate default processor.
*
* It's not supposed to be overwritten.
*
* @return
*/
public final static NodeProcessor getDefaultProc() {
return new DefaultPruner();
}
}