Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
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.pcr;
 
 import java.util.List;
 import java.util.Map;
 
Expression processor factory for partition condition removing. Each processor tries to calculate a result vector from its children's result vectors. Each element is the result for one of the pruned partitions. It also generates node by Modifying expr trees with partition conditions removed
 
 public final class PcrExprProcFactory {
   static Object evalExprWithPart(ExprNodeDesc exprPartition pthrows SemanticException {
     StructObjectInspector rowObjectInspector;
     Table tbl = p.getTable();
     LinkedHashMap<StringStringpartSpec = p.getSpec();
 
     try {
       rowObjectInspector = (StructObjectInspectortbl
           .getDeserializer().getObjectInspector();
     } catch (SerDeException e) {
       throw new SemanticException(e);
     }
 
     try {
       return PartExprEvalUtils.evalExprWithPart(exprpartSpecrowObjectInspector);
     } catch (HiveException e) {
       throw new SemanticException(e);
     }
   }
 
   static Boolean ifResultsAgree(Boolean[] resultVector) {
     Boolean result = null;
     for (Boolean b : resultVector) {
       if (b == null) {
         return null;
       } else if (result == null) {
         result = b;
       } else if (!result.equals(b)) {
         return null;
       }
     }
     return result;
   }
 
   static Object ifResultsAgree(Object[] resultVector) {
     Object result = null;
     for (Object b : resultVector) {
       if (b == null) {
         return null;
       } else if (result == null) {
         result = b;
      } else if (!result.equals(b)) {
        return null;
      }
    }
    return result;
  }
      ExprNodeGenericFuncDesc fdObject[] nodeOutputs) {
    Boolean ifAgree = ifResultsAgree(results);
    if (ifAgree == null) {
      return new NodeInfoWrapper(.results,
          getOutExpr(fdnodeOutputs));
    } else if (ifAgree.booleanValue() == true) {
      return new NodeInfoWrapper(.null,
          new ExprNodeConstantDesc(fd.getTypeInfo(), .));
    } else {
      return new NodeInfoWrapper(.null,
          new ExprNodeConstantDesc(fd.getTypeInfo(), .));
    }
  }
  private PcrExprProcFactory() {
    // prevent instantiation
  }
  static Boolean opAnd(Boolean op1Boolean op2) {
    if (op1.equals(.) || op2.equals(.)) {
      return .;
    }
    if (op1 == null || op2 == null) {
      return null;
    }
    return .;
  }
  static Boolean opOr(Boolean op1Boolean op2) {
    if (op1.equals(.) || op2.equals(.)) {
      return .;
    }
    if (op1 == null || op2 == null) {
      return null;
    }
    return .;
  }
  static Boolean opNot(Boolean op) {
    if (op.equals(.)) {
      return .;
    }
    if (op.equals(.)) {
      return .;
    }
    return null;
  }
  public enum WalkState {
    PART_COL, TRUE, FALSE, CONSTANT, UNKNOWN, DIVIDED
  }
  public static class NodeInfoWrapper {
    public NodeInfoWrapper(WalkState stateBoolean[] resultVectorExprNodeDesc outExpr) {
      super();
      this. = state;
       = resultVector;
      this. = outExpr;
    }
    public Boolean[] ResultVector;
    public ExprNodeDesc outExpr;
  }

  
Processor for column expressions.
  public static class ColumnExprProcessor implements NodeProcessor {
    @Override
    public Object process(Node ndStack<NodestackNodeProcessorCtx procCtx,
        Object... nodeOutputsthrows SemanticException {
      ExprNodeColumnDesc cd = (ExprNodeColumnDescnd;
      PcrExprProcCtx epc = (PcrExprProcCtxprocCtx;
      if (cd.getTabAlias().equalsIgnoreCase(epc.getTabAlias())
          && cd.getIsPartitionColOrVirtualCol()) {
        return new NodeInfoWrapper(.nullcd);
      } else {
        return new NodeInfoWrapper(.nullcd);
      }
    }
  }
      ExprNodeGenericFuncDesc funcExprObject[] nodeOutputs) {
    ArrayList<ExprNodeDescchildren = new ArrayList<ExprNodeDesc>();
    if (nodeOutputs != null) {
      for (Object child : nodeOutputs) {
        NodeInfoWrapper wrapper = (NodeInfoWrapperchild;
        children.add(wrapper.outExpr);
      }
    }
    funcExpr.setChildExprs(children);
    return funcExpr;
  }

  
Processor for Generic functions If it is AND, OR or NOT, we replace the node to be the constant true or false if we are sure the result from children, or cut one of the child if we know partial results. In case of both child has a result vector, we calculate the result vector for the node. If all partitions agree on a result, we replace the node with constant true or false. Otherwise, we pass the vector result. For other Generic functions, if it is non-deterministic we simply pass it (with children adjusted based on results from children). If it is deterministic, we evaluate result vector if any of the children is partition column. Otherwise, we pass it as it is.
  public static class GenericFuncExprProcessor implements NodeProcessor {
    @Override
    public Object process(Node ndStack<NodestackNodeProcessorCtx procCtx,
        Object... nodeOutputsthrows SemanticException {
      PcrExprProcCtx ctx = (PcrExprProcCtxprocCtx;
      if (FunctionRegistry.isOpNot(fd)) {
        assert (nodeOutputs.length == 1);
        NodeInfoWrapper wrapper = (NodeInfoWrappernodeOutputs[0];
        if (wrapper.state == .) {
          ExprNodeConstantDesc falseDesc = new ExprNodeConstantDesc(
              wrapper.outExpr.getTypeInfo(), .);
          return new NodeInfoWrapper(.nullfalseDesc);
        } else if (wrapper.state == .) {
          ExprNodeConstantDesc trueDesc = new ExprNodeConstantDesc(
              wrapper.outExpr.getTypeInfo(), .);
          return new NodeInfoWrapper(.nulltrueDesc);
        } else if (wrapper.state == .) {
          Boolean[] results = new Boolean[ctx.getPartList().size()];
          for (int i = 0; i < ctx.getPartList().size(); i++) {
            results[i] = opNot(wrapper.ResultVector[i]);
          }
          return new NodeInfoWrapper(.results,
              getOutExpr(fdnodeOutputs));
        } else {
          return new NodeInfoWrapper(wrapper.statenull,
              getOutExpr(fdnodeOutputs));
        }
      } else if (FunctionRegistry.isOpAnd(fd)) {
        assert (nodeOutputs.length == 2);
        NodeInfoWrapper c1 = (NodeInfoWrapper)nodeOutputs[0];
        NodeInfoWrapper c2 = (NodeInfoWrapper)nodeOutputs[1];
        if (c1.state == .) {
          return c1;
        } else if (c2.state == .) {
          return c2;
        } else if (c1.state == .) {
          return c2;
        } else if (c2.state == .) {
          return c1;
        } else if (c1.state == . || c2.state == .) {
          return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
        } else if (c1.state == . && c2.state == .) {
          Boolean[] results = new Boolean[ctx.getPartList().size()];
          for (int i = 0; i < ctx.getPartList().size(); i++) {
            results[i] = opAnd(c1.ResultVector[i], c2.ResultVector[i]);
          }
          return getResultWrapFromResults(resultsfdnodeOutputs);
        }
        return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
      } else if (FunctionRegistry.isOpOr(fd)) {
        assert (nodeOutputs.length == 2);
        NodeInfoWrapper c1 = (NodeInfoWrapper)nodeOutputs[0];
        NodeInfoWrapper c2 = (NodeInfoWrapper)nodeOutputs[1];
        if (c1.state == .) {
          return c1;
        } else if (c2.state == .) {
          return c2;
        } else if (c1.state == .) {
          return c2;
        } else if (c2.state == .) {
          return c1;
        } else if (c1.state == . || c2.state == .) {
          return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
        } else if (c1.state == . && c2.state == .) {
          Boolean[] results = new Boolean[ctx.getPartList().size()];
          for (int i = 0; i < ctx.getPartList().size(); i++) {
            results[i] = opOr(c1.ResultVector[i], c2.ResultVector[i]);
          }
          return getResultWrapFromResults(resultsfdnodeOutputs);
        }
        return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
      } else if (!FunctionRegistry.isDeterministic(fd.getGenericUDF())) {
        // If it's a non-deterministic UDF, set unknown to true
        return new NodeInfoWrapper(.null,
            getOutExpr(fdnodeOutputs));
      } else {
        // If any child is unknown, set unknown to true
        boolean has_part_col = false;
        for (Object child : nodeOutputs) {
          NodeInfoWrapper wrapper = (NodeInfoWrapperchild;
          if (wrapper.state == .) {
            return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
          } else if (wrapper.state == .) {
            has_part_col = true;
          }
        }
        if (has_part_col) {
          //  we need to evaluate result for every pruned partition
          if (fd.getTypeInfo().equals(.)) {
            // if the return type of the GenericUDF is boolean and all partitions agree on
            // a result, we update the state of the node to be TRUE of FALSE
            Boolean[] results = new Boolean[ctx.getPartList().size()];
            for (int i = 0; i < ctx.getPartList().size(); i++) {
              results[i] = (BooleanevalExprWithPart(fdctx.getPartList().get(i));
            }
            return getResultWrapFromResults(resultsfdnodeOutputs);
          }
          // the case that return type of the GenericUDF is not boolean, and if not all partition
          // agree on result, we make the node UNKNOWN. If they all agree, we replace the node
          // to be a CONSTANT node with value to be the agreed result.
          Object[] results = new Object[ctx.getPartList().size()];
          for (int i = 0; i < ctx.getPartList().size(); i++) {
            results[i] = evalExprWithPart(fdctx.getPartList().get(i));
          }
          Object result = ifResultsAgree(results);
          if (result == null) {
            // if the result is not boolean and not all partition agree on the
            // result, we don't remove the condition. Potentially, it can miss
            // the case like "where ds % 3 == 1 or ds % 3 == 2"
            // TODO: handle this case by making result vector to handle all
            // constant values.
            return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
          }
          return new NodeInfoWrapper(.null,
              new ExprNodeConstantDesc(fd.getTypeInfo(), result));
        }
        return new NodeInfoWrapper(.nullgetOutExpr(fdnodeOutputs));
      }
    }
  };

  
FieldExprProcessor.
  public static class FieldExprProcessor implements NodeProcessor {
    @Override
    public Object process(Node ndStack<NodestackNodeProcessorCtx procCtx,
        Object... nodeOutputsthrows SemanticException {
      ExprNodeFieldDesc fnd = (ExprNodeFieldDescnd;
      boolean unknown = false;
      int idx = 0;
      for (Object child : nodeOutputs) {
        NodeInfoWrapper wrapper = (NodeInfoWrapperchild;
        if (wrapper.state == .) {
          unknown = true;
        }
      }
      assert (idx == 0);
      if (unknown) {
        return new NodeInfoWrapper(.nullfnd);
      } else {
        return new NodeInfoWrapper(.nullfnd);
      }
    }
  }

  
Processor for constants and null expressions. For such expressions the processor simply returns.
  public static class DefaultExprProcessor implements NodeProcessor {
    @Override
    public Object process(Node ndStack<NodestackNodeProcessorCtx procCtx,
        Object... nodeOutputsthrows SemanticException {
      if (nd instanceof ExprNodeConstantDesc || nd instanceof ExprNodeNullDesc) {
        return new NodeInfoWrapper(.null,
            (ExprNodeDescnd);
      }
      assert (false);
      return null;
    }
  }
  public static NodeProcessor getDefaultExprProcessor() {
    return new DefaultExprProcessor();
  }
  public static NodeProcessor getGenericFuncProcessor() {
    return new GenericFuncExprProcessor();
  }
  public static NodeProcessor getFieldProcessor() {
    return new FieldExprProcessor();
  }
  public static NodeProcessor getColumnProcessor() {
    return new ColumnExprProcessor();
  }

  
Remove partition conditions when necessary from the the expression tree.

Parameters:
tabAlias the table alias
parts the list of all pruned partitions for the
pred expression tree of the target filter operator
Returns:
the node information of the root expression
Throws:
org.apache.hadoop.hive.ql.parse.SemanticException
  public static NodeInfoWrapper walkExprTree(
      String tabAliasArrayList<PartitionpartsExprNodeDesc pred)
      throws SemanticException {
    // Create the walker, the rules dispatcher and the context.
    PcrExprProcCtx pprCtx = new PcrExprProcCtx(tabAliasparts);
    Map<RuleNodeProcessorexprRules = new LinkedHashMap<RuleNodeProcessor>();
    exprRules.put(
        new RuleRegExp("R1"ExprNodeColumnDesc.class.getName() + "%"),
        getColumnProcessor());
    exprRules.put(
        new RuleRegExp("R2"ExprNodeFieldDesc.class.getName() + "%"),
        getFieldProcessor());
    exprRules.put(new RuleRegExp("R5"ExprNodeGenericFuncDesc.class.getName()
        + "%"), getGenericFuncProcessor());
    // The dispatcher fires the processor corresponding to the closest matching
    // rule and passes the context along
        exprRulespprCtx);
    GraphWalker egw = new DefaultGraphWalker(disp);
    List<NodestartNodes = new ArrayList<Node>();
    startNodes.add(pred);
    HashMap<NodeObjectoutputMap = new HashMap<NodeObject>();
    egw.startWalking(startNodesoutputMap);
    // Return the wrapper of the root node
    return (NodeInfoWrapperoutputMap.get(pred);
  }
New to GrepCode? Check out our FAQ X