Package org.apache.drill.exec.expr

Source Code of org.apache.drill.exec.expr.EvaluationVisitor

/**
* 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.drill.exec.expr;

import java.util.Collections;
import java.util.Set;

import org.apache.drill.common.expression.FunctionCall;
import org.apache.drill.common.expression.IfExpression;
import org.apache.drill.common.expression.IfExpression.IfCondition;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.expression.SchemaPath;
import org.apache.drill.common.expression.ValueExpressions.BooleanExpression;
import org.apache.drill.common.expression.ValueExpressions.DoubleExpression;
import org.apache.drill.common.expression.ValueExpressions.LongExpression;
import org.apache.drill.common.expression.ValueExpressions.QuotedString;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.common.types.Types;
import org.apache.drill.exec.expr.CodeGenerator.BlockType;
import org.apache.drill.exec.expr.CodeGenerator.HoldingContainer;
import org.apache.drill.exec.expr.fn.DrillFuncHolder;
import org.apache.drill.exec.expr.fn.FunctionImplementationRegistry;
import org.apache.drill.exec.physical.impl.filter.ReturnValueExpression;
import org.apache.drill.exec.record.NullExpression;
import org.apache.drill.exec.vector.ValueHolderHelper;

import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JConditional;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JType;
import com.sun.codemodel.JVar;

public class EvaluationVisitor {

  private final FunctionImplementationRegistry registry;
 
  public EvaluationVisitor(FunctionImplementationRegistry registry) {
    super();
    this.registry = registry;
  }

  public HoldingContainer addExpr(LogicalExpression e, CodeGenerator<?> generator){
//    Set<LogicalExpression> constantBoundaries = ConstantExpressionIdentifier.getConstantExpressionSet(e);
    Set<LogicalExpression> constantBoundaries = Collections.emptySet();
    return e.accept(new ConstantFilter(constantBoundaries), generator);
   
  }

  private class EvalVisitor extends AbstractExprVisitor<HoldingContainer, CodeGenerator<?>, RuntimeException> {

   
    @Override
    public HoldingContainer visitFunctionCall(FunctionCall call, CodeGenerator<?> generator) throws RuntimeException {
      DrillFuncHolder holder = registry.getFunction(call);
      JVar[] workspaceVars = holder.renderStart(generator, null);

     
      if(holder.isNested()) generator.getMappingSet().enterChild();
      HoldingContainer[] args = new HoldingContainer[call.args.size()];
      for (int i = 0; i < call.args.size(); i++) {
        args[i] = call.args.get(i).accept(this, generator);
      }
      holder.renderMiddle(generator, args, workspaceVars);
      if(holder.isNested()) generator.getMappingSet().exitChild();
      return holder.renderEnd(generator, args, workspaceVars);
    }

    @Override
    public HoldingContainer visitIfExpression(IfExpression ifExpr, CodeGenerator<?> generator) throws RuntimeException {
      JBlock local = generator.getEvalBlock();

      HoldingContainer output = generator.declare(ifExpr.getMajorType());

      JConditional jc = null;
      JBlock conditionalBlock = new JBlock(false, false);
      for (IfCondition c : ifExpr.conditions) {
        HoldingContainer HoldingContainer = c.condition.accept(this, generator);
        if (jc == null) {
          if (HoldingContainer.isOptional()) {
            jc = conditionalBlock._if(HoldingContainer.getIsSet().cand(HoldingContainer.getValue()));
          } else {
            jc = conditionalBlock._if(HoldingContainer.getValue());
          }
        } else {
          if (HoldingContainer.isOptional()) {
            jc = jc._else()._if(HoldingContainer.getIsSet().cand(HoldingContainer.getValue()));
          } else {
            jc = jc._else()._if(HoldingContainer.getValue());
          }
        }

        HoldingContainer thenExpr = c.expression.accept(this, generator);
        if (thenExpr.isOptional()) {
          JConditional newCond = jc._then()._if(thenExpr.getIsSet());
          JBlock b = newCond._then();
          b.assign(output.getValue(), thenExpr.getValue());
          b.assign(output.getIsSet(), thenExpr.getIsSet());
        } else {
          jc._then().assign(output.getValue(), thenExpr.getValue());
        }

      }

      HoldingContainer elseExpr = ifExpr.elseExpression.accept(this, generator);
      if (elseExpr.isOptional()) {
        JConditional newCond = jc._else()._if(elseExpr.getIsSet());
        JBlock b = newCond._then();
        b.assign(output.getValue(), elseExpr.getValue());
        b.assign(output.getIsSet(), elseExpr.getIsSet());
      } else {
        jc._else().assign(output.getValue(), elseExpr.getValue());

      }
      local.add(conditionalBlock);
      return output;
    }

   
    @Override
    public HoldingContainer visitSchemaPath(SchemaPath path, CodeGenerator<?> generator) throws RuntimeException {
      throw new UnsupportedOperationException("All schema paths should have been replaced with ValueVectorExpressions.");
    }

    @Override
    public HoldingContainer visitLongConstant(LongExpression e, CodeGenerator<?> generator) throws RuntimeException {
      HoldingContainer out = generator.declare(e.getMajorType());
      generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getLong()));
      return out;
    }

    @Override
    public HoldingContainer visitDoubleConstant(DoubleExpression e, CodeGenerator<?> generator) throws RuntimeException {
      HoldingContainer out = generator.declare(e.getMajorType());
      generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getDouble()));
      return out;
    }

    @Override
    public HoldingContainer visitBooleanConstant(BooleanExpression e, CodeGenerator<?> generator)
        throws RuntimeException {
      HoldingContainer out = generator.declare(e.getMajorType());
      generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getBoolean() ? 1 : 0));
      return out;
    }

    @Override
    public HoldingContainer visitUnknown(LogicalExpression e, CodeGenerator<?> generator) throws RuntimeException {
      if (e instanceof ValueVectorReadExpression) {
        return visitValueVectorReadExpression((ValueVectorReadExpression) e, generator);
      } else if (e instanceof ValueVectorWriteExpression) {
        return visitValueVectorWriteExpression((ValueVectorWriteExpression) e, generator);
      } else if (e instanceof ReturnValueExpression) {
        return visitReturnValueExpression((ReturnValueExpression) e, generator);
      }else if(e instanceof HoldingContainerExpression){
        return ((HoldingContainerExpression) e).getContainer();
      }else if(e instanceof NullExpression){
        return generator.declare(Types.optional(MinorType.INT));
      } else {
        return super.visitUnknown(e, generator);
      }

    }

    private HoldingContainer visitValueVectorWriteExpression(ValueVectorWriteExpression e, CodeGenerator<?> generator) {

      LogicalExpression child = e.getChild();
      HoldingContainer inputContainer = child.accept(this, generator);
      JBlock block = generator.getEvalBlock();
      JExpression outIndex = generator.getMappingSet().getValueWriteIndex();
      JVar vv = generator.declareVectorValueSetupAndMember(generator.getMappingSet().getOutgoing(), e.getFieldId());
      String setMethod = e.isSafe() ? "setSafe" : "set";
     
      JInvocation setMeth;
      if (Types.usesHolderForGet(inputContainer.getMajorType())) {
        setMeth = vv.invoke("getMutator").invoke(setMethod).arg(outIndex).arg(inputContainer.getHolder());
      }else{
        setMeth = vv.invoke("getMutator").invoke(setMethod).arg(outIndex).arg(inputContainer.getValue());
      }
     
      if(e.isSafe()){
        HoldingContainer outputContainer = generator.declare(Types.REQUIRED_BIT);
        block.assign(outputContainer.getValue(), JExpr.lit(1));
        if(inputContainer.isOptional()){
//          block._if(vv.invoke("getMutator").invoke(setMethod).arg(outIndex).not())._then().assign(outputContainer.getValue(), JExpr.lit(0));
          JConditional jc = block._if(inputContainer.getIsSet().eq(JExpr.lit(0)).not());
          block = jc._then();
        }
        block._if(setMeth.not())._then().assign(outputContainer.getValue(), JExpr.lit(0));
        return outputContainer;
      }else{
        if (inputContainer.isOptional()) {
//          block.add(vv.invoke("getMutator").invoke(setMethod).arg(outIndex));
          JConditional jc = block._if(inputContainer.getIsSet().eq(JExpr.lit(0)).not());
          block = jc._then();
        }
        block.add(setMeth);
      }
     
      return null;
    }

    private HoldingContainer visitValueVectorReadExpression(ValueVectorReadExpression e, CodeGenerator<?> generator)
        throws RuntimeException {
      // declare value vector
     
      JVar vv1 = generator.declareVectorValueSetupAndMember(generator.getMappingSet().getIncoming(), e.getFieldId());
      JExpression indexVariable = generator.getMappingSet().getValueReadIndex();

      JInvocation getValueAccessor = vv1.invoke("getAccessor").invoke("get");
      JInvocation getValueAccessor2 = vv1.invoke("getAccessor");
      if (e.isSuperReader()) {

        getValueAccessor = ((JExpression) vv1.component(indexVariable.shrz(JExpr.lit(16)))).invoke("getAccessor").invoke("get");
        getValueAccessor2 = ((JExpression) vv1.component(indexVariable.shrz(JExpr.lit(16)))).invoke("getAccessor");
        indexVariable = indexVariable.band(JExpr.lit((int) Character.MAX_VALUE));
      }

      // evaluation work.
      HoldingContainer out = generator.declare(e.getMajorType());

      if (out.isOptional()) {
        JBlock blk = generator.getEvalBlock();
        blk.assign(out.getIsSet(), getValueAccessor2.invoke("isSet").arg(indexVariable));
        JConditional jc = blk._if(out.getIsSet().eq(JExpr.lit(1)));
        if (Types.usesHolderForGet(e.getMajorType())) {
          jc._then().add(getValueAccessor.arg(indexVariable).arg(out.getHolder()));
        } else {
          jc._then().assign(out.getValue(), getValueAccessor.arg(indexVariable));
        }
      } else {
        if (Types.usesHolderForGet(e.getMajorType())) {
          generator.getEvalBlock().add(getValueAccessor.arg(indexVariable).arg(out.getHolder()));
        } else {
          generator.getEvalBlock().assign(out.getValue(), getValueAccessor.arg(indexVariable));
        }
      }
      return out;
    }

    private HoldingContainer visitReturnValueExpression(ReturnValueExpression e, CodeGenerator<?> generator) {
      LogicalExpression child = e.getChild();
      // Preconditions.checkArgument(child.getMajorType().equals(Types.REQUIRED_BOOLEAN));
      HoldingContainer hc = child.accept(this, generator);
      if(e.isReturnTrueOnOne()){
        generator.getEvalBlock()._return(hc.getValue().eq(JExpr.lit(1)))
      }else{
        generator.getEvalBlock()._return(hc.getValue());
      }
     
      return null;
    }

    @Override
    public HoldingContainer visitQuotedStringConstant(QuotedString e, CodeGenerator<?> generator)
        throws RuntimeException {
      MajorType majorType = Types.required(MinorType.VARCHAR);
      JBlock setup = generator.getBlock(BlockType.SETUP);
      JType holderType = generator.getHolderType(majorType);
      JVar var = generator.declareClassField("string", holderType);
      JExpression stringLiteral = JExpr.lit(e.value);
      setup.assign(var, ((JClass)generator.getModel().ref(ValueHolderHelper.class)).staticInvoke("getVarCharHolder").arg(stringLiteral));
      return new HoldingContainer(majorType, var, null, null);
     
    }
  }

  private class ConstantFilter extends EvalVisitor {

    private Set<LogicalExpression> constantBoundaries;
   
   
    public ConstantFilter(Set<LogicalExpression> constantBoundaries) {
      super();
      this.constantBoundaries = constantBoundaries;
    }

    @Override
    public HoldingContainer visitFunctionCall(FunctionCall e, CodeGenerator<?> generator) throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitFunctionCall(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitFunctionCall(e, generator);
      }
    }

    @Override
    public HoldingContainer visitIfExpression(IfExpression e, CodeGenerator<?> generator) throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitIfExpression(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitIfExpression(e, generator);
      }
    }

    @Override
    public HoldingContainer visitSchemaPath(SchemaPath e, CodeGenerator<?> generator) throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitSchemaPath(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitSchemaPath(e, generator);
      }
    }

    @Override
    public HoldingContainer visitLongConstant(LongExpression e, CodeGenerator<?> generator) throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitLongConstant(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitLongConstant(e, generator);
      }
    }

    @Override
    public HoldingContainer visitDoubleConstant(DoubleExpression e, CodeGenerator<?> generator) throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitDoubleConstant(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitDoubleConstant(e, generator);
      }
    }

    @Override
    public HoldingContainer visitBooleanConstant(BooleanExpression e, CodeGenerator<?> generator)
        throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitBooleanConstant(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitBooleanConstant(e, generator);
      }
    }

   
    @Override
    public HoldingContainer visitUnknown(LogicalExpression e, CodeGenerator<?> generator) throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitUnknown(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitUnknown(e, generator);
      }
    }

    @Override
    public HoldingContainer visitQuotedStringConstant(QuotedString e, CodeGenerator<?> generator)
        throws RuntimeException {
      if (constantBoundaries.contains(e)) {
        generator.getMappingSet().enterConstant();
        HoldingContainer c = super.visitQuotedStringConstant(e, generator);
        generator.getMappingSet().exitConstant();
        return c;
      } else {
        return super.visitQuotedStringConstant(e, generator);
      }
    }

  }
}
TOP

Related Classes of org.apache.drill.exec.expr.EvaluationVisitor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.