/**
* 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.unionproc;
import java.io.Serializable;
import java.util.List;
import java.util.Stack;
import org.apache.hadoop.hive.ql.exec.Operator;
import org.apache.hadoop.hive.ql.exec.UnionOperator;
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.optimizer.unionproc.UnionProcContext.UnionParseContext;
import org.apache.hadoop.hive.ql.parse.SemanticException;
/**
* Operator factory for union processing.
*/
public final class UnionProcFactory {
private UnionProcFactory() {
// prevent instantiation
}
public static int getPositionParent(UnionOperator union, Stack<Node> stack) {
int pos = 0;
int size = stack.size();
assert size >= 2 && stack.get(size - 1) == union;
Operator<? extends Serializable> parent = (Operator<? extends Serializable>) stack
.get(size - 2);
List<Operator<? extends Serializable>> parUnion = union
.getParentOperators();
pos = parUnion.indexOf(parent);
assert pos < parUnion.size();
return pos;
}
/**
* MapRed subquery followed by Union.
*/
public static class MapRedUnion implements NodeProcessor {
@Override
public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
UnionOperator union = (UnionOperator) nd;
UnionProcContext ctx = (UnionProcContext) procCtx;
// find the branch on which this processor was invoked
int pos = getPositionParent(union, stack);
UnionParseContext uCtx = ctx.getUnionParseContext(union);
if (uCtx == null) {
uCtx = new UnionParseContext(union.getConf().getNumInputs());
}
ctx.setMapOnlySubq(false);
uCtx.setMapOnlySubq(pos, false);
uCtx.setRootTask(pos, false);
ctx.setUnionParseContext(union, uCtx);
return null;
}
}
/**
* Map-only subquery followed by Union.
*/
public static class MapUnion implements NodeProcessor {
@Override
public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
UnionOperator union = (UnionOperator) nd;
UnionProcContext ctx = (UnionProcContext) procCtx;
// find the branch on which this processor was invoked
int pos = getPositionParent(union, stack);
UnionParseContext uCtx = ctx.getUnionParseContext(union);
if (uCtx == null) {
uCtx = new UnionParseContext(union.getConf().getNumInputs());
}
uCtx.setMapOnlySubq(pos, true);
uCtx.setRootTask(pos, true);
ctx.setUnionParseContext(union, uCtx);
return null;
}
}
/**
* Map-join subquery followed by Union.
*/
public static class MapJoinUnion implements NodeProcessor {
@Override
public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
UnionOperator union = (UnionOperator) nd;
UnionProcContext ctx = (UnionProcContext) procCtx;
// find the branch on which this processor was invoked
int pos = getPositionParent(union, stack);
UnionParseContext uCtx = ctx.getUnionParseContext(union);
if (uCtx == null) {
uCtx = new UnionParseContext(union.getConf().getNumInputs());
}
uCtx.setMapJoinSubq(pos, true);
ctx.setUnionParseContext(union, uCtx);
return null;
}
}
/**
* Union subquery followed by Union.
*/
public static class UnknownUnion implements NodeProcessor {
@Override
public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
UnionOperator union = (UnionOperator) nd;
UnionProcContext ctx = (UnionProcContext) procCtx;
// find the branch on which this processor was invoked
int pos = getPositionParent(union, stack);
UnionParseContext uCtx = ctx.getUnionParseContext(union);
if (uCtx == null) {
uCtx = new UnionParseContext(union.getConf().getNumInputs());
}
int start = stack.size() - 2;
UnionOperator parentUnionOperator = null;
while (start >= 0) {
Operator<? extends Serializable> parent =
(Operator<? extends Serializable>) stack.get(start);
if (parent instanceof UnionOperator) {
parentUnionOperator = (UnionOperator) parent;
break;
}
start--;
}
// default to false
boolean mapOnly = false;
if (parentUnionOperator != null) {
UnionParseContext parentUCtx =
ctx.getUnionParseContext(parentUnionOperator);
if (parentUCtx != null && parentUCtx.allMapOnlySubQSet()) {
mapOnly = parentUCtx.allMapOnlySubQ();
}
}
uCtx.setMapOnlySubq(pos, mapOnly);
uCtx.setRootTask(pos, false);
ctx.setUnionParseContext(union, uCtx);
return null;
}
}
/**
* Default processor.
*/
public static class NoUnion implements NodeProcessor {
@Override
public Object process(Node nd, Stack<Node> stack, NodeProcessorCtx procCtx,
Object... nodeOutputs) throws SemanticException {
return null;
}
}
public static NodeProcessor getMapRedUnion() {
return new MapRedUnion();
}
public static NodeProcessor getMapUnion() {
return new MapUnion();
}
public static NodeProcessor getMapJoinUnion() {
return new MapJoinUnion();
}
public static NodeProcessor getUnknownUnion() {
return new UnknownUnion();
}
public static NodeProcessor getNoUnion() {
return new NoUnion();
}
}