http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
new file mode 100644
index 0000000..c57f923
--- /dev/null
+++ 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/EvalCodeGenerator.java
@@ -0,0 +1,840 @@
+/**
+ * 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.tajo.engine.codegen;
+
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.FunctionDesc;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.IntervalDatum;
+import org.apache.tajo.datum.ProtobufDatum;
+import org.apache.tajo.engine.eval.*;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.org.objectweb.asm.*;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.storage.VTuple;
+
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.util.Stack;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+import static org.apache.tajo.engine.codegen.TajoGeneratorAdapter.*;
+import static org.apache.tajo.engine.eval.FunctionEval.ParamType;
+
+public class EvalCodeGenerator extends 
SimpleEvalNodeVisitor<EvalCodeGenContext> {
+
+  public static final byte UNKNOWN = 0;
+  public static final byte TRUE = 1;
+  public static final byte FALSE = 2;
+
+  /** 0 - UNKNOWN, 1 - TRUE, 2 - FALSE */
+  @SuppressWarnings("unused")
+  public static final byte [] THREE_VALUES = new byte[]  {UNKNOWN, TRUE, 
FALSE};
+  @SuppressWarnings("unused")
+  public static final byte [] NOT_LOGIC =    new byte[] {UNKNOWN, FALSE, TRUE};
+  @SuppressWarnings("unused")
+  public static final byte [][] AND_LOGIC = new byte [][] {
+      //          unknown  true     false
+      new byte [] {UNKNOWN, UNKNOWN, FALSE},   // unknown
+      new byte [] {UNKNOWN, TRUE,    FALSE},   // true
+      new byte [] {FALSE,   FALSE,   FALSE}    // false
+  };
+  @SuppressWarnings("unused")
+  public static final byte [][] OR_LOGIC = new byte [][] {
+      //          unknown  true     false
+      new byte [] {UNKNOWN, TRUE,    UNKNOWN}, // unknown
+      new byte [] {TRUE,    TRUE,    TRUE},    // true
+      new byte [] {UNKNOWN, TRUE,    FALSE}    // false
+  };
+
+  private final TajoClassLoader classLoader;
+  static int classSeq = 1;
+
+  public EvalCodeGenerator(TajoClassLoader classLoader) {
+    this.classLoader = classLoader;
+  }
+
+  public EvalNode compile(Schema schema, EvalNode expr) throws 
CompilationError {
+
+    ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+
+    String className = EvalCodeGenerator.class.getPackage().getName() + 
".CompiledEval" + classSeq++;
+    EvalCodeGenContext context = new 
EvalCodeGenContext(TajoGeneratorAdapter.getInternalName(className),
+        schema, classWriter, expr);
+    visit(context, expr, new Stack<EvalNode>());
+    context.emitReturn();
+
+    Class aClass = classLoader.defineClass(className, 
classWriter.toByteArray());
+
+    Constructor constructor;
+    EvalNode compiledEval;
+
+    try {
+      constructor = aClass.getConstructor();
+      compiledEval = (EvalNode) constructor.newInstance();
+    } catch (Throwable t) {
+      throw new CompilationError(expr, t, classWriter.toByteArray());
+    }
+    return compiledEval;
+  }
+
+  private void printOut(EvalCodeGenContext context, String message) {
+    context.methodvisitor.visitFieldInsn(Opcodes.GETSTATIC, 
"java/lang/System", "out", "Ljava/io/PrintStream;");
+    context.push(message);
+    context.invokeVirtual(PrintStream.class, "println", void.class, new 
Class[]{String.class});
+  }
+
+  public EvalNode visitBinaryEval(EvalCodeGenContext context, Stack<EvalNode> 
stack, BinaryEval binaryEval) {
+    if (EvalType.isLogicalOperator(binaryEval.getType())) {
+      return visitAndOrEval(context, binaryEval, stack);
+    } else if (EvalType.isArithmeticOperator(binaryEval.getType())) {
+      return visitArithmeticEval(context, binaryEval, stack);
+    } else if (EvalType.isComparisonOperator(binaryEval.getType())) {
+      return visitComparisonEval(context, binaryEval, stack);
+    } else if (binaryEval.getType() == EvalType.CONCATENATE) {
+      return visitStringConcat(context, binaryEval, stack);
+    } else if (binaryEval.getType() == EvalType.LIKE || binaryEval.getType() 
== EvalType.SIMILAR_TO
+        || binaryEval.getType() == EvalType.REGEX) {
+      return visitStringPatternMatch(context, binaryEval, stack);
+    } else if (binaryEval.getType() == EvalType.IN) {
+      return visitInPredicate(context, binaryEval, stack);
+    } else {
+      stack.push(binaryEval);
+      visit(context, binaryEval.getLeftExpr(), stack);
+      visit(context, binaryEval.getRightExpr(), stack);
+      stack.pop();
+      return binaryEval;
+    }
+  }
+
+  public EvalNode visitUnaryEval(EvalCodeGenContext context, Stack<EvalNode> 
stack, UnaryEval unary) {
+    stack.push(unary);
+    if (unary.getType() == EvalType.CAST) {
+      visitCast(context, stack, (CastEval) unary);
+
+    } else if (unary.getType() == EvalType.NOT) {
+
+      visit(context, unary.getChild(), stack);
+      context.methodvisitor.visitVarInsn(Opcodes.ISTORE, 9);
+      context.methodvisitor.visitVarInsn(Opcodes.ISTORE, 10);
+
+      Label ifNull = new Label();
+      Label endIf = new Label();
+
+      context.emitNullityCheck(ifNull, 9);
+
+      context.methodvisitor.visitFieldInsn(Opcodes.GETSTATIC, 
Type.getInternalName(EvalCodeGenerator.class),
+          "NOT_LOGIC", "[B");
+      context.methodvisitor.visitVarInsn(Opcodes.ILOAD, 10);
+      context.methodvisitor.visitInsn(Opcodes.BALOAD);
+      context.pushNullFlag(true);
+      emitGotoLabel(context, endIf);
+
+      emitLabel(context, ifNull);
+      context.pushDummyValue(unary.getValueType());
+      context.pushNullFlag(false);
+
+      emitLabel(context, endIf);
+
+    } else if (unary.getType() == EvalType.IS_NULL) {
+      return visitIsNull(context, (IsNullEval) unary, stack);
+
+
+    } else if (unary.getType() == EvalType.SIGNED) {
+      visit(context, unary.getChild(), stack);
+
+      Label ifNull = new Label();
+      Label endIf = new Label();
+
+      context.emitNullityCheck(ifNull);
+
+      SignedEval signed = (SignedEval) unary;
+      switch (signed.getValueType().getType()) {
+      case BOOLEAN:
+      case CHAR:
+      case INT1:
+      case INT2:
+      case INT4: context.methodvisitor.visitInsn(Opcodes.INEG); break;
+      case INT8: context.methodvisitor.visitInsn(Opcodes.LNEG); break;
+      case FLOAT4: context.methodvisitor.visitInsn(Opcodes.FNEG); break;
+      case FLOAT8: context.methodvisitor.visitInsn(Opcodes.DNEG); break;
+      default: throw new InvalidEvalException(unary.getType() + " operation to 
" + signed.getChild() + " is invalid.");
+      }
+
+      context.pushNullFlag(true);
+      emitGotoLabel(context, endIf);
+
+      emitLabel(context, ifNull);
+      context.pushNullFlag(false);
+
+      emitLabel(context, endIf);
+
+    } else {
+      super.visit(context, unary, stack);
+    }
+    stack.pop();
+    return unary;
+  }
+
+  public EvalNode visitBetween(EvalCodeGenContext context, 
BetweenPredicateEval between, Stack<EvalNode> stack) {
+    EvalNode predicand = between.getPredicand();
+    EvalNode begin = between.getBegin();
+    EvalNode end = between.getEnd();
+
+    stack.push(between);
+
+    visit(context, predicand, stack);
+    final int PREDICAND_NULLFLAG = context.istore();
+    final int PREDICAND = context.store(predicand.getValueType());
+
+    visit(context, begin, stack);
+    final int BEGIN_NULLFLAG = context.istore();
+    final int BEGIN = context.store(begin.getValueType());
+
+    visit(context, end, stack);                                         // < 
end, right_nullflag
+    final int END_NULLFLAG = context.istore();
+    final int END = context.store(end.getValueType());                         
       // <
+
+    stack.pop();
+
+    Label ifNullCommon = new Label();
+    Label ifNotMatched = new Label();
+
+    Label afterEnd = new Label();
+
+
+    context.emitNullityCheck(ifNullCommon, PREDICAND_NULLFLAG, BEGIN_NULLFLAG, 
END_NULLFLAG);
+
+    if (between.isSymmetric()) {
+      Label ifFirstMatchFailed = new Label();
+      Label ifSecondMatchFailed = new Label();
+      Label secondCheck = new Label();
+      Label finalDisjunctive = new Label();
+
+      
//////////////////////////////////////////////////////////////////////////////////////////
+      // second check
+      
//////////////////////////////////////////////////////////////////////////////////////////
+
+      // predicand <= begin
+      context.load(begin.getValueType(), BEGIN);
+      context.load(predicand.getValueType(), PREDICAND);
+      context.ifCmp(predicand.getValueType(), EvalType.LEQ, 
ifFirstMatchFailed);
+
+      // end <= predicand
+      context.load(end.getValueType(), END);
+      context.load(predicand.getValueType(), PREDICAND);
+      // inverse the operator GEQ -> LTH
+      context.ifCmp(predicand.getValueType(), EvalType.GEQ, 
ifFirstMatchFailed);
+
+      context.push(true);
+      emitGotoLabel(context, secondCheck);
+
+      emitLabel(context, ifFirstMatchFailed);
+      context.push(false);
+
+      
//////////////////////////////////////////////////////////////////////////////////////////
+      // second check
+      
//////////////////////////////////////////////////////////////////////////////////////////
+      emitLabel(context, secondCheck);
+
+      // predicand <= end
+      context.load(end.getValueType(), END);
+      context.load(predicand.getValueType(), PREDICAND);
+
+      // inverse the operator LEQ -> GTH
+      context.ifCmp(predicand.getValueType(), EvalType.LEQ, 
ifSecondMatchFailed);
+
+      // end <= predicand
+      context.load(begin.getValueType(), BEGIN);
+      context.load(predicand.getValueType(), PREDICAND);
+      // inverse the operator GEQ -> LTH
+      context.ifCmp(predicand.getValueType(), EvalType.GEQ, 
ifSecondMatchFailed);
+
+      context.push(true);
+      emitGotoLabel(context, finalDisjunctive);
+
+      emitLabel(context, ifSecondMatchFailed);
+      context.push(false);
+
+      emitLabel(context, finalDisjunctive);
+      context.methodvisitor.visitInsn(Opcodes.IOR);
+      context.methodvisitor.visitJumpInsn(Opcodes.IFEQ, ifNotMatched);
+    } else {
+      // predicand <= begin
+      context.load(begin.getValueType(), BEGIN);
+      context.load(predicand.getValueType(), PREDICAND);
+      context.ifCmp(predicand.getValueType(), EvalType.LEQ, ifNotMatched);
+
+      // end <= predicand
+      context.load(end.getValueType(), END);
+      context.load(predicand.getValueType(), PREDICAND);
+      context.ifCmp(predicand.getValueType(), EvalType.GEQ, ifNotMatched);
+    }
+
+    // IF MATCHED
+    context.pushBooleanOfThreeValuedLogic(between.isNot() ? false : true);
+    context.pushNullFlag(true);
+    emitGotoLabel(context, afterEnd);
+
+    emitLabel(context, ifNotMatched); // IF NOT MATCHED
+    context.pushBooleanOfThreeValuedLogic(between.isNot() ? true : false);
+    context.pushNullFlag(true);
+    emitGotoLabel(context, afterEnd);
+
+    emitLabel(context, ifNullCommon); // IF NULL
+    context.pushNullOfThreeValuedLogic();
+    context.pushNullFlag(false);
+
+    emitLabel(context, afterEnd);
+
+    return between;
+  }
+
+  private void emitGotoLabel(EvalCodeGenContext context, Label label) {
+    context.methodvisitor.visitJumpInsn(Opcodes.GOTO, label);
+  }
+
+  void emitLabel(EvalCodeGenContext context, Label label) {
+    context.methodvisitor.visitLabel(label);
+  }
+
+  public EvalNode visitCast(EvalCodeGenContext context, Stack<EvalNode> stack, 
CastEval cast) {
+    DataType  srcType = cast.getOperand().getValueType();
+    DataType targetType = cast.getValueType();
+
+    if (srcType.equals(targetType)) {
+      visit(context, cast.getChild(), stack);
+      return cast;
+    }
+
+    visit(context, cast.getChild(), stack);
+
+    Label ifNull = new Label();
+    Label afterEnd = new Label();
+    context.emitNullityCheck(ifNull);
+
+    context.castInsn(srcType, targetType);
+    context.pushNullFlag(true);
+    emitGotoLabel(context, afterEnd);
+
+    emitLabel(context, ifNull);
+    context.pop(srcType);
+    context.pushDummyValue(targetType);
+    context.pushNullFlag(false);
+    printOut(context, "endIfNull");
+
+    emitLabel(context, afterEnd);
+    return cast;
+  }
+
+  public EvalNode visitField(EvalCodeGenContext context, Stack<EvalNode> 
stack, FieldEval field) {
+
+    if (field.getValueType().getType() == TajoDataTypes.Type.NULL_TYPE) {
+      context.pushNullOfThreeValuedLogic();
+      context.pushNullFlag(false);
+    } else {
+
+      Column columnRef = field.getColumnRef();
+      int fieldIdx;
+      if (columnRef.hasQualifier()) {
+        fieldIdx = context.schema.getColumnId(columnRef.getQualifiedName());
+      } else {
+        fieldIdx = context.schema.getColumnIdByName(columnRef.getSimpleName());
+      }
+
+      context.methodvisitor.visitVarInsn(Opcodes.ALOAD, 2);
+      context.push(fieldIdx);
+      context.invokeInterface(Tuple.class, "isNull", boolean.class, new Class 
[] {int.class});
+
+      context.push(true);
+
+      Label ifNull = new Label();
+      Label afterAll = new Label();
+      context.methodvisitor.visitJumpInsn(Opcodes.IF_ICMPEQ, ifNull);
+
+      String methodName = null;
+      Class returnType = null;
+      Class [] paramTypes = null;
+      switch (field.getValueType().getType()) {
+      case BOOLEAN:
+        methodName = "getByte";
+        returnType = byte.class;
+        paramTypes = new Class[] {int.class};
+        break;
+      case CHAR: {
+        methodName = "getText";
+        returnType = String.class;
+        paramTypes = new Class[] {int.class};
+        break;
+      }
+      case INT1:
+      case INT2:
+      case INT4:
+      case DATE:
+      case INET4:
+        methodName = "getInt4";
+        returnType = int.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      case INT8:
+      case TIMESTAMP:
+      case TIME:
+        methodName = "getInt8";
+        returnType = long.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      case FLOAT4:
+        methodName = "getFloat4";
+        returnType = float.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      case FLOAT8:
+        methodName = "getFloat8";
+        returnType = double.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      case TEXT:
+        methodName = "getText";
+        returnType = String.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      case INTERVAL:
+        methodName = "getInterval";
+        returnType = IntervalDatum.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      case PROTOBUF:
+        methodName = "getProtobufDatum";
+        returnType = ProtobufDatum.class;
+        paramTypes = new Class [] {int.class};
+        break;
+      default:
+        throw new InvalidEvalException(field.getValueType() + " is not 
supported yet");
+      }
+
+      context.methodvisitor.visitVarInsn(Opcodes.ALOAD, 2);
+      context.push(fieldIdx);
+      context.invokeInterface(Tuple.class, methodName, returnType, paramTypes);
+
+      context.pushNullFlag(true); // not null
+      context.methodvisitor.visitJumpInsn(Opcodes.GOTO, afterAll);
+
+      context.methodvisitor.visitLabel(ifNull);
+      context.pushDummyValue(field.getValueType());
+      context.pushNullFlag(false);
+
+      context.methodvisitor.visitLabel(afterAll);
+    }
+    return field;
+  }
+
+  public EvalNode visitAndOrEval(EvalCodeGenContext context, BinaryEval 
evalNode, Stack<EvalNode> stack) {
+
+    stack.push(evalNode);
+    visit(context, evalNode.getLeftExpr(), stack);
+    context.pop();
+    int LHS = context.istore();
+
+    visit(context, evalNode.getRightExpr(), stack);
+    context.pop();
+    int RHS = context.istore();
+    stack.pop();
+
+    if (evalNode.getType() == EvalType.AND) {
+      context.methodvisitor.visitFieldInsn(Opcodes.GETSTATIC,
+          
org.apache.tajo.org.objectweb.asm.Type.getInternalName(EvalCodeGenerator.class),
 "AND_LOGIC", "[[B");
+    } else if (evalNode.getType() == EvalType.OR) {
+      context.methodvisitor.visitFieldInsn(Opcodes.GETSTATIC,
+          
org.apache.tajo.org.objectweb.asm.Type.getInternalName(EvalCodeGenerator.class),
 "OR_LOGIC", "[[B");
+    } else {
+      throw new CompilationError("visitAndOrEval() cannot generate the code at 
" + evalNode);
+    }
+    context.load(evalNode.getLeftExpr().getValueType(), LHS);
+    context.methodvisitor.visitInsn(Opcodes.AALOAD);
+    context.load(evalNode.getRightExpr().getValueType(), RHS);
+    context.methodvisitor.visitInsn(Opcodes.BALOAD);    // get three valued 
logic number from the AND/OR_LOGIC array
+    context.methodvisitor.visitInsn(Opcodes.DUP); // three valued logic number 
x 2, three valued logic number can be null flag.
+
+    return evalNode;
+  }
+
+  public static int store(EvalCodeGenContext context, DataType type, int idx) {
+    switch (type.getType()) {
+    case NULL_TYPE:
+    case BOOLEAN:
+    case CHAR:
+    case INT1:
+    case INT2:
+    case INT4:
+      context.methodvisitor.visitVarInsn(Opcodes.ISTORE, idx);
+      break;
+    case INT8: context.methodvisitor.visitVarInsn(Opcodes.LSTORE, idx); break;
+    case FLOAT4: context.methodvisitor.visitVarInsn(Opcodes.FSTORE, idx); 
break;
+    case FLOAT8: context.methodvisitor.visitVarInsn(Opcodes.DSTORE, idx); 
break;
+    default: context.methodvisitor.visitVarInsn(Opcodes.ASTORE, idx); break;
+    }
+
+    return idx + TajoGeneratorAdapter.getWordSize(type);
+  }
+
+  public EvalNode visitArithmeticEval(EvalCodeGenContext context, BinaryEval 
evalNode, Stack<EvalNode> stack) {
+    stack.push(evalNode);
+    visit(context, evalNode.getLeftExpr(), stack);          // < left_child, 
push nullflag
+    int LHS_NULLFLAG = context.istore();
+    int LHS = context.store(evalNode.getLeftExpr().getValueType());
+
+    visit(context, evalNode.getRightExpr(), stack);         // < left_child, 
right_child, nullflag
+    int RHS_NULLFLAG = context.istore();
+    int RHS = context.store(evalNode.getRightExpr().getValueType());
+    stack.pop();
+
+    Label ifNull = new Label();
+    Label afterEnd = new Label();
+
+    context.emitNullityCheck(ifNull, LHS_NULLFLAG, RHS_NULLFLAG);
+
+    context.load(evalNode.getLeftExpr().getValueType(), LHS);
+    context.load(evalNode.getRightExpr().getValueType(), RHS);
+
+    int opCode = TajoGeneratorAdapter.getOpCode(evalNode.getType(), 
evalNode.getValueType());
+    context.methodvisitor.visitInsn(opCode);
+
+    context.pushNullFlag(true);
+    emitGotoLabel(context, afterEnd);
+
+    emitLabel(context, ifNull);
+    context.pushDummyValue(evalNode.getValueType());
+    context.pushNullFlag(false);
+
+    emitLabel(context, afterEnd);
+
+    return evalNode;
+  }
+
+  public EvalNode visitComparisonEval(EvalCodeGenContext context, BinaryEval 
evalNode, Stack<EvalNode> stack)
+      throws CompilationError {
+
+    DataType lhsType = evalNode.getLeftExpr().getValueType();
+    DataType rhsType = evalNode.getRightExpr().getValueType();
+
+    if (lhsType.getType() == TajoDataTypes.Type.NULL_TYPE || rhsType.getType() 
== TajoDataTypes.Type.NULL_TYPE) {
+      context.pushNullOfThreeValuedLogic();
+      context.pushNullFlag(false);
+    } else {
+      stack.push(evalNode);
+      visit(context, evalNode.getLeftExpr(), stack);                    // < 
lhs, l_null
+      final int LHS_NULLFLAG = context.istore();
+      int LHS = context.store(evalNode.getLeftExpr().getValueType());   // <
+
+      visit(context, evalNode.getRightExpr(), stack);                   // < 
rhs, r_nullflag
+      final int RHS_NULLFLAG = context.istore();
+      final int RHS = context.store(evalNode.getRightExpr().getValueType());   
        // <
+      stack.pop();
+
+      Label ifNull = new Label();
+      Label ifNotMatched = new Label();
+      Label afterEnd = new Label();
+
+      context.emitNullityCheck(ifNull, LHS_NULLFLAG, RHS_NULLFLAG);
+
+      context.load(evalNode.getLeftExpr().getValueType(), LHS);             // 
< lhs
+      context.load(evalNode.getRightExpr().getValueType(), RHS);            // 
< lhs, rhs
+
+      context.ifCmp(evalNode.getLeftExpr().getValueType(), evalNode.getType(), 
ifNotMatched);
+
+      context.pushBooleanOfThreeValuedLogic(true);
+      context.pushNullFlag(true);
+      context.methodvisitor.visitJumpInsn(Opcodes.GOTO, afterEnd);
+
+      context.methodvisitor.visitLabel(ifNotMatched);
+      context.pushBooleanOfThreeValuedLogic(false);
+      context.pushNullFlag(true);
+      context.methodvisitor.visitJumpInsn(Opcodes.GOTO, afterEnd);
+
+      context.methodvisitor.visitLabel(ifNull);
+      context.pushNullOfThreeValuedLogic();
+      context.pushNullFlag(false);
+
+      context.methodvisitor.visitLabel(afterEnd);
+    }
+
+    return evalNode;
+  }
+
+  public EvalNode visitStringConcat(EvalCodeGenContext context, BinaryEval 
evalNode, Stack<EvalNode> stack)
+      throws CompilationError {
+
+    stack.push(evalNode);
+
+    visit(context, evalNode.getLeftExpr(), stack);                    // < 
lhs, l_null
+    final int LHS_NULLFLAG = context.istore();               // < lhs
+    final int LHS = context.store(evalNode.getLeftExpr().getValueType());
+
+    visit(context, evalNode.getRightExpr(), stack);                   // < 
rhs, r_nullflag
+    int RHS_NULLFLAG = context.istore();
+    int RHS = context.store(evalNode.getRightExpr().getValueType());           
// <
+    stack.pop();
+
+    Label ifNull = new Label();
+    Label afterEnd = new Label();
+
+    context.emitNullityCheck(ifNull, LHS_NULLFLAG, RHS_NULLFLAG);
+
+    context.load(evalNode.getLeftExpr().getValueType(), LHS);                  
   // < lhs
+    context.load(evalNode.getRightExpr().getValueType(), RHS);            // < 
lhs, rhs
+
+    context.invokeVirtual(String.class, "concat", String.class, new Class[] 
{String.class});
+    context.pushNullFlag(true);
+    context.methodvisitor.visitJumpInsn(Opcodes.GOTO, afterEnd);
+
+    context.methodvisitor.visitLabel(ifNull);
+    context.pushDummyValue(evalNode.getValueType());
+    context.pushNullFlag(false);
+
+    context.methodvisitor.visitLabel(afterEnd);
+
+    return evalNode;
+  }
+
+  public EvalNode visitIsNull(EvalCodeGenContext context, IsNullEval 
isNullEval, Stack<EvalNode> stack) {
+
+    visit(context, isNullEval.getChild(), stack);
+
+    Label ifNull = new Label();
+    Label endIf = new Label();
+
+    context.emitNullityCheck(ifNull);
+
+    context.pop(isNullEval.getChild().getValueType());
+    context.pushBooleanOfThreeValuedLogic(isNullEval.isNot() ? true : false);
+    context.methodvisitor.visitJumpInsn(Opcodes.GOTO, endIf);
+
+    context.methodvisitor.visitLabel(ifNull);
+    context.pop(isNullEval.getChild().getValueType());
+    context.pushBooleanOfThreeValuedLogic(isNullEval.isNot() ? false : true);
+
+    emitLabel(context, endIf);
+    context.methodvisitor.visitInsn(Opcodes.ICONST_1); // NOT NULL
+
+    return isNullEval;
+  }
+
+
+  @Override
+  public EvalNode visitConst(EvalCodeGenContext context, ConstEval constEval, 
Stack<EvalNode> stack) {
+    switch (constEval.getValueType().getType()) {
+    case NULL_TYPE:
+
+      if (stack.isEmpty()) {
+        context.pushNullOfThreeValuedLogic();
+      } else {
+        EvalNode parentNode = stack.peek();
+
+        if (parentNode instanceof BinaryEval) {
+          BinaryEval parent = (BinaryEval) stack.peek();
+          if (parent.getLeftExpr() == constEval) {
+            context.pushDummyValue(parent.getRightExpr().getValueType());
+          } else {
+            context.pushDummyValue(parent.getLeftExpr().getValueType());
+          }
+        } else if (parentNode instanceof CaseWhenEval) {
+          CaseWhenEval caseWhen = (CaseWhenEval) parentNode;
+          context.pushDummyValue(caseWhen.getValueType());
+        } else {
+          throw new CompilationError("Cannot find matched type in the stack: " 
+ constEval);
+        }
+      }
+      break;
+    case BOOLEAN:
+      context.push(constEval.getValue().asInt4());
+      break;
+
+    case INT1:
+    case INT2:
+    case INT4:
+    case DATE:
+      context.push(constEval.getValue().asInt4());
+      break;
+    case INT8:
+    case TIMESTAMP:
+    case TIME:
+      context.push(constEval.getValue().asInt8());
+      break;
+    case FLOAT4:
+      context.push(constEval.getValue().asFloat4());
+      break;
+    case FLOAT8:
+      context.push(constEval.getValue().asFloat8());
+      break;
+    case CHAR:
+    case TEXT:
+      context.push(constEval.getValue().asChars());
+      break;
+    case INTERVAL:
+      // load pre-stored variable.
+      emitGetField(context, context.owner, context.symbols.get(constEval), 
IntervalDatum.class);
+      break;
+    default:
+      throw new 
UnsupportedOperationException(constEval.getValueType().getType().name() +
+          " const type is not supported");
+    }
+
+    context.pushNullFlag(constEval.getValueType().getType() != 
TajoDataTypes.Type.NULL_TYPE);
+    return constEval;
+  }
+
+  public static ParamType [] getParamTypes(EvalNode [] arguments) {
+    ParamType[] paramTypes = new ParamType[arguments.length];
+    for (int i = 0; i < arguments.length; i++) {
+      if (arguments[i].getType() == EvalType.CONST) {
+        if (arguments[i].getValueType().getType() == 
TajoDataTypes.Type.NULL_TYPE) {
+          paramTypes[i] = ParamType.NULL;
+        } else {
+          paramTypes[i] = ParamType.CONSTANT;
+        }
+      } else {
+        paramTypes[i] = ParamType.VARIABLE;
+      }
+    }
+    return paramTypes;
+  }
+
+  @Override
+  public EvalNode visitFuncCall(EvalCodeGenContext context, FunctionEval func, 
Stack<EvalNode> stack) {
+    int paramNum = func.getArgs().length;
+    context.push(paramNum);
+    context.newArray(Datum.class); // new Datum[paramNum]
+    final int DATUM_ARRAY = context.astore();
+
+    stack.push(func);
+    EvalNode [] params = func.getArgs();
+    for (int paramIdx = 0; paramIdx < func.getArgs().length; paramIdx++) {
+      context.aload(DATUM_ARRAY);       // array ref
+      context.methodvisitor.visitLdcInsn(paramIdx); // array idx
+      visit(context, params[paramIdx], stack);
+      context.convertToDatum(params[paramIdx].getValueType(), true);  // value
+      context.methodvisitor.visitInsn(Opcodes.AASTORE);
+    }
+    stack.pop();
+
+    context.methodvisitor.visitTypeInsn(Opcodes.NEW, 
TajoGeneratorAdapter.getInternalName(VTuple.class));
+    context.methodvisitor.visitInsn(Opcodes.DUP);
+    context.aload(DATUM_ARRAY);
+    context.newInstance(VTuple.class, new Class[]{Datum[].class});  // new 
VTuple(datum [])
+    context.methodvisitor.visitTypeInsn(Opcodes.CHECKCAST, 
TajoGeneratorAdapter.getInternalName(Tuple.class)); // cast to Tuple
+    final int TUPLE = context.astore();
+
+    FunctionDesc desc = func.getFuncDesc();
+
+    String fieldName = context.symbols.get(func);
+    String funcDescName = "L" + 
TajoGeneratorAdapter.getInternalName(desc.getFuncClass()) + ";";
+
+    context.aload(0);
+    context.methodvisitor.visitFieldInsn(Opcodes.GETFIELD, context.owner, 
fieldName, funcDescName);
+    context.aload(TUPLE);
+    context.invokeVirtual(desc.getFuncClass(), "eval", Datum.class, new 
Class[] {Tuple.class});
+
+    context.convertToPrimitive(func.getValueType());
+    return func;
+  }
+
+  public EvalNode visitInPredicate(EvalCodeGenContext context, EvalNode 
patternEval, Stack<EvalNode> stack) {
+    String fieldName = context.symbols.get(patternEval);
+    emitGetField(context, context.owner, fieldName, InEval.class);
+    if (context.schema != null) {
+      emitGetField(context, context.owner, "schema", Schema.class);
+    } else {
+      context.methodvisitor.visitInsn(Opcodes.ACONST_NULL);
+    }
+    context.aload(2); // tuple
+    context.invokeVirtual(InEval.class, "eval", Datum.class, new 
Class[]{Schema.class, Tuple.class});
+    context.convertToPrimitive(patternEval.getValueType());
+
+    return patternEval;
+  }
+
+  protected EvalNode visitStringPatternMatch(EvalCodeGenContext context, 
EvalNode patternEval, Stack<EvalNode> stack) {
+    Class clazz = getStringPatternEvalClass(patternEval.getType());
+    String fieldName = context.symbols.get(patternEval);
+    emitGetField(context, context.owner, fieldName, clazz);
+    if (context.schema != null) {
+      emitGetField(context, context.owner, "schema", Schema.class);
+    } else {
+      context.methodvisitor.visitInsn(Opcodes.ACONST_NULL);
+    }
+    context.aload(2); // tuple
+    context.invokeVirtual(clazz, "eval", Datum.class, new 
Class[]{Schema.class, Tuple.class});
+    context.convertToPrimitive(patternEval.getValueType());
+
+    return patternEval;
+  }
+
+  protected static void emitGetField(EvalCodeGenContext context, String owner, 
String fieldName, Class clazz) {
+    context.aload(0);
+    context.methodvisitor.visitFieldInsn(Opcodes.GETFIELD, owner, fieldName, 
getDescription(clazz));
+  }
+
+  public static Class getStringPatternEvalClass(EvalType type) {
+    if (type == EvalType.LIKE) {
+      return LikePredicateEval.class;
+    } else if (type == EvalType.SIMILAR_TO) {
+      return SimilarToPredicateEval.class;
+    } else {
+      return RegexPredicateEval.class;
+    }
+  }
+
+  @SuppressWarnings("unused")
+  public static EvalNode createEval(String json) {
+    return CoreGsonHelper.fromJson(json, EvalNode.class);
+  }
+
+  @SuppressWarnings("unused")
+  public static ConstEval createConstEval(String json) {
+    return (ConstEval) CoreGsonHelper.fromJson(json, EvalNode.class);
+  }
+
+  @SuppressWarnings("unused")
+  public static RowConstantEval createRowConstantEval(String json) {
+    return (RowConstantEval) CoreGsonHelper.fromJson(json, EvalNode.class);
+  }
+
+  @SuppressWarnings("unused")
+  public static Schema createSchema(String json) {
+    return CoreGsonHelper.fromJson(json, Schema.class);
+  }
+
+  @Override
+  protected EvalNode visitCaseWhen(EvalCodeGenContext context, CaseWhenEval 
caseWhen, Stack<EvalNode> stack) {
+    CaseWhenEmitter.getInstance().emit(this, context, caseWhen, stack);
+    return caseWhen;
+  }
+
+  @Override
+  protected EvalNode visitIfThen(EvalCodeGenContext context, 
CaseWhenEval.IfThenEval evalNode, Stack<EvalNode> stack) {
+    stack.push(evalNode);
+    visit(context, evalNode.getCondition(), stack);
+    visit(context, evalNode.getResult(), stack);
+    stack.pop();
+    return evalNode;
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/codegen/ExecutorPreCompiler.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/ExecutorPreCompiler.java
 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/ExecutorPreCompiler.java
new file mode 100644
index 0000000..54d857b
--- /dev/null
+++ 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/ExecutorPreCompiler.java
@@ -0,0 +1,213 @@
+/*
+ * 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.tajo.engine.codegen;
+
+import com.google.common.collect.Maps;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.planner.*;
+import org.apache.tajo.engine.planner.logical.*;
+import org.apache.tajo.util.Pair;
+
+import java.util.Collections;
+import java.util.Map;
+import java.util.Stack;
+
+public class ExecutorPreCompiler extends 
BasicLogicalPlanVisitor<ExecutorPreCompiler.CompilationContext, LogicalNode> {
+  private static final Log LOG = LogFactory.getLog(ExecutorPreCompiler.class);
+
+  private static final ExecutorPreCompiler instance;
+
+  static {
+    instance = new ExecutorPreCompiler();
+  }
+
+  public static void compile(CompilationContext context, LogicalNode node) 
throws PlanningException {
+    instance.visit(context, null, null, node, new Stack<LogicalNode>());
+    context.compiledEval = Collections.unmodifiableMap(context.compiledEval);
+  }
+
+  public static Map<Pair<Schema, EvalNode>, EvalNode> compile(TajoClassLoader 
classLoader, LogicalNode node)
+      throws PlanningException {
+    CompilationContext context = new CompilationContext(classLoader);
+    instance.visit(context, null, null, node, new Stack<LogicalNode>());
+    return context.compiledEval;
+  }
+
+  public static class CompilationContext {
+    private final EvalCodeGenerator compiler;
+    private Map<Pair<Schema,EvalNode>, EvalNode> compiledEval;
+
+    public CompilationContext(TajoClassLoader classLoader) {
+      this.compiler = new EvalCodeGenerator(classLoader);
+      this.compiledEval = Maps.newHashMap();
+    }
+
+    public EvalCodeGenerator getCompiler() {
+      return compiler;
+    }
+
+    public Map<Pair<Schema, EvalNode>, EvalNode> getPrecompiedEvals() {
+      return compiledEval;
+    }
+  }
+
+  private static void compileIfAbsent(CompilationContext context, Schema 
schema, EvalNode eval) {
+    Pair<Schema, EvalNode> key = new Pair<Schema, EvalNode>(schema, eval);
+    if (!context.compiledEval.containsKey(key)) {
+      try {
+        EvalNode compiled = context.compiler.compile(schema, eval);
+        context.compiledEval.put(key, compiled);
+
+      } catch (Throwable t) {
+        // If any compilation error occurs, it works in a fallback mode. This 
mode just uses EvalNode objects
+        // instead of a compiled EvalNode.
+        context.compiledEval.put(key, eval);
+        LOG.warn(t);
+      }
+    }
+  }
+
+  private static void compileProjectableNode(CompilationContext context, 
Schema schema, Projectable node) {
+    Target [] targets;
+    if (node.hasTargets()) {
+      targets = node.getTargets();
+    } else {
+      targets = PlannerUtil.schemaToTargets(node.getOutSchema());
+    }
+
+    for (Target target : targets) {
+      compileIfAbsent(context, schema, target.getEvalTree());
+    }
+  }
+
+  private static void compileSelectableNode(CompilationContext context, Schema 
schema, SelectableNode node) {
+    if (node.hasQual()) {
+      compileIfAbsent(context, schema, node.getQual());
+    }
+  }
+
+  @Override
+  public LogicalNode visitProjection(CompilationContext context, LogicalPlan 
plan, LogicalPlan.QueryBlock block,
+                                     ProjectionNode node, Stack<LogicalNode> 
stack) throws PlanningException {
+    super.visitProjection(context, plan, block, node, stack);
+
+    compileProjectableNode(context, node.getInSchema(), node);
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitHaving(CompilationContext context, LogicalPlan plan, 
LogicalPlan.QueryBlock block,
+                                 HavingNode node, Stack<LogicalNode> stack) 
throws PlanningException {
+    super.visitHaving(context, plan, block, node, stack);
+
+    compileSelectableNode(context, node.getInSchema(), node);
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitGroupBy(CompilationContext context, LogicalPlan 
plan, LogicalPlan.QueryBlock block,
+                                  GroupbyNode node, Stack<LogicalNode> stack) 
throws PlanningException {
+    super.visitGroupBy(context, plan, block, node, stack);
+
+    compileProjectableNode(context, node.getInSchema(), node);
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitWindowAgg(CompilationContext context, LogicalPlan 
plan, LogicalPlan.QueryBlock block,
+                                    WindowAggNode node, Stack<LogicalNode> 
stack) throws PlanningException {
+    super.visitWindowAgg(context, plan, block, node, stack);
+
+    compileProjectableNode(context, node.getInSchema(), node);
+
+    return node;
+  }
+
+  public LogicalNode visitDistinct(CompilationContext context, LogicalPlan 
plan, LogicalPlan.QueryBlock block,
+                                   DistinctGroupbyNode node, 
Stack<LogicalNode> stack) throws PlanningException {
+    super.visitDistinct(context, plan, block, node, stack);
+
+    compileProjectableNode(context, node.getInSchema(), node);
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitFilter(CompilationContext context, LogicalPlan plan, 
LogicalPlan.QueryBlock block,
+                                 SelectionNode node, Stack<LogicalNode> stack) 
throws PlanningException {
+    super.visitFilter(context, plan, block, node, stack);
+
+    compileSelectableNode(context, node.getInSchema(), node);
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitJoin(CompilationContext context, LogicalPlan plan, 
LogicalPlan.QueryBlock block,
+                               JoinNode node, Stack<LogicalNode> stack) throws 
PlanningException {
+    super.visitJoin(context, plan, block, node, stack);
+
+    compileProjectableNode(context, node.getInSchema(), node);
+
+    if (node.hasJoinQual()) {
+      compileIfAbsent(context, node.getInSchema(), node.getJoinQual());
+    }
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitTableSubQuery(CompilationContext context, 
LogicalPlan plan, LogicalPlan.QueryBlock block,
+                                   TableSubQueryNode node, Stack<LogicalNode> 
stack) throws PlanningException {
+    stack.push(node);
+    visit(context, plan, null, node.getSubQuery(), stack);
+    stack.pop();
+
+    if (node.hasTargets()) {
+      for (Target target : node.getTargets()) {
+        compileIfAbsent(context, node.getTableSchema(), target.getEvalTree());
+      }
+    }
+
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitPartitionedTableScan(CompilationContext context, 
LogicalPlan plan,
+                                               LogicalPlan.QueryBlock block, 
PartitionedTableScanNode node,
+                                               Stack<LogicalNode> stack) 
throws PlanningException {
+    visitScan(context, plan, block, node, stack);
+    return node;
+  }
+
+  @Override
+  public LogicalNode visitScan(CompilationContext context, LogicalPlan plan, 
LogicalPlan.QueryBlock block,
+                               ScanNode node, Stack<LogicalNode> stack) throws 
PlanningException {
+
+    compileProjectableNode(context, node.getInSchema(), node);
+    compileSelectableNode(context, node.getInSchema(), node);
+
+    return node;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoClassLoader.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoClassLoader.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoClassLoader.java
new file mode 100644
index 0000000..16be3b0
--- /dev/null
+++ 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoClassLoader.java
@@ -0,0 +1,30 @@
+/**
+ * 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.tajo.engine.codegen;
+
+public class TajoClassLoader extends ClassLoader {
+
+  public Class defineClass(String name, byte[] b) {
+    return defineClass(name, b, 0, b.length);
+  }
+
+  public void clean() throws Throwable {
+    super.finalize();
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
new file mode 100644
index 0000000..6fac1a8
--- /dev/null
+++ 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/TajoGeneratorAdapter.java
@@ -0,0 +1,953 @@
+/**
+ * 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.tajo.engine.codegen;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.*;
+import org.apache.tajo.engine.eval.EvalNode;
+import org.apache.tajo.engine.eval.EvalType;
+import org.apache.tajo.exception.InvalidCastException;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.util.TUtil;
+import org.apache.tajo.util.datetime.DateTimeUtil;
+import org.apache.tajo.org.objectweb.asm.Label;
+import org.apache.tajo.org.objectweb.asm.MethodVisitor;
+import org.apache.tajo.org.objectweb.asm.Opcodes;
+import org.apache.tajo.org.objectweb.asm.Type;
+import org.apache.tajo.org.objectweb.asm.commons.GeneratorAdapter;
+import org.apache.tajo.org.objectweb.asm.commons.TableSwitchGenerator;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.tajo.common.TajoDataTypes.Type.*;
+
+class TajoGeneratorAdapter {
+
+  public static final Map<EvalType, Map<TajoDataTypes.Type, Integer>> 
OpCodesMap = Maps.newHashMap();
+
+  static {
+    TUtil.putToNestedMap(OpCodesMap, EvalType.PLUS, INT1, Opcodes.IADD);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.PLUS, INT2, Opcodes.IADD);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.PLUS, INT4, Opcodes.IADD);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.PLUS, INT8, Opcodes.LADD);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.PLUS, FLOAT4, Opcodes.FADD);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.PLUS, FLOAT8, Opcodes.DADD);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MINUS, INT1, Opcodes.ISUB);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MINUS, INT2, Opcodes.ISUB);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MINUS, INT4, Opcodes.ISUB);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MINUS, INT8, Opcodes.LSUB);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MINUS, FLOAT4, Opcodes.FSUB);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MINUS, FLOAT8, Opcodes.DSUB);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MULTIPLY, INT1, Opcodes.IMUL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MULTIPLY, INT2, Opcodes.IMUL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MULTIPLY, INT4, Opcodes.IMUL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MULTIPLY, INT8, Opcodes.LMUL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MULTIPLY, FLOAT4, Opcodes.FMUL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MULTIPLY, FLOAT8, Opcodes.DMUL);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.DIVIDE, INT1, Opcodes.IDIV);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.DIVIDE, INT2, Opcodes.IDIV);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.DIVIDE, INT4, Opcodes.IDIV);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.DIVIDE, INT8, Opcodes.LDIV);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.DIVIDE, FLOAT4, Opcodes.FDIV);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.DIVIDE, FLOAT8, Opcodes.DDIV);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MODULAR, INT1, Opcodes.IREM);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MODULAR, INT2, Opcodes.IREM);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MODULAR, INT4, Opcodes.IREM);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MODULAR, INT8, Opcodes.LREM);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MODULAR, FLOAT4, Opcodes.FREM);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.MODULAR, FLOAT8, Opcodes.DREM);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_AND, INT1, Opcodes.IAND);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_AND, INT2, Opcodes.IAND);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_AND, INT4, Opcodes.IAND);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_AND, INT8, Opcodes.LAND);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_OR, INT1, Opcodes.IOR);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_OR, INT2, Opcodes.IOR);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_OR, INT4, Opcodes.IOR);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_OR, INT8, Opcodes.LOR);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_XOR, INT1, Opcodes.IXOR);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_XOR, INT2, Opcodes.IXOR);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_XOR, INT4, Opcodes.IXOR);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.BIT_XOR, INT8, Opcodes.LXOR);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, INT1, Opcodes.IF_ICMPEQ);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, INT2, Opcodes.IF_ICMPEQ);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, INT4, Opcodes.IF_ICMPEQ);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, FLOAT4, Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, FLOAT8, Opcodes.DCMPG);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.EQUAL, TEXT, Opcodes.IF_ACMPNE);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, INT1, 
Opcodes.IF_ICMPNE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, INT2, 
Opcodes.IF_ICMPNE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, INT4, 
Opcodes.IF_ICMPNE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, FLOAT4, 
Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, FLOAT8, 
Opcodes.DCMPG);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.NOT_EQUAL, TEXT, 
Opcodes.IF_ACMPNE);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT1, Opcodes.IF_ICMPLT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT2, Opcodes.IF_ICMPLT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT4, Opcodes.IF_ICMPLT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, FLOAT4, Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, FLOAT8, Opcodes.DCMPG);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT1, Opcodes.IF_ICMPLT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT2, Opcodes.IF_ICMPLT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT4, Opcodes.IF_ICMPLT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, FLOAT4, Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LTH, FLOAT8, Opcodes.DCMPG);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LEQ, INT1, Opcodes.IF_ICMPLE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LEQ, INT2, Opcodes.IF_ICMPLE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LEQ, INT4, Opcodes.IF_ICMPLE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LEQ, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LEQ, FLOAT4, Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.LEQ, FLOAT8, Opcodes.DCMPG);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GTH, INT1, Opcodes.IF_ICMPGT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GTH, INT2, Opcodes.IF_ICMPGT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GTH, INT4, Opcodes.IF_ICMPGT);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GTH, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GTH, FLOAT4, Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GTH, FLOAT8, Opcodes.DCMPG);
+
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GEQ, INT1, Opcodes.IF_ICMPGE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GEQ, INT2, Opcodes.IF_ICMPGE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GEQ, INT4, Opcodes.IF_ICMPGE);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GEQ, INT8, Opcodes.LCMP);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GEQ, FLOAT4, Opcodes.FCMPL);
+    TUtil.putToNestedMap(OpCodesMap, EvalType.GEQ, FLOAT8, Opcodes.DCMPG);
+  }
+
+  protected int access;
+  protected MethodVisitor methodvisitor;
+  protected GeneratorAdapter generatorAdapter;
+
+  public TajoGeneratorAdapter() {}
+
+  public TajoGeneratorAdapter(int access, MethodVisitor methodVisitor, String 
name, String desc) {
+    this.access = access;
+    this.methodvisitor = methodVisitor;
+    generatorAdapter = new GeneratorAdapter(methodVisitor, access, name, desc);
+  }
+
+  public static boolean isJVMInternalInt(TajoDataTypes.DataType dataType) {
+    TajoDataTypes.Type type = dataType.getType();
+    return type == BOOLEAN || type == INT1 || type == INT2 || type == INT4 || 
type== INET4;
+  }
+
+  public static int getWordSize(TajoDataTypes.DataType type) {
+    if (type.getType() == INT8 || type.getType() == FLOAT8 || type.getType() 
== TIMESTAMP || type.getType() == TIME) {
+      return 2;
+    } else {
+      return 1;
+    }
+  }
+
+  public void push(final boolean value) {
+    methodvisitor.visitInsn(value ? Opcodes.ICONST_1 : Opcodes.ICONST_0);
+  }
+
+  public void push(final int value) {
+    if (value >= -1 && value <= 5) {
+      methodvisitor.visitInsn(Opcodes.ICONST_0 + value);
+    } else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
+      methodvisitor.visitIntInsn(Opcodes.BIPUSH, value);
+    } else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
+      methodvisitor.visitIntInsn(Opcodes.SIPUSH, value);
+    } else {
+      methodvisitor.visitLdcInsn(new Integer(value));
+    }
+  }
+
+  public void push(final long value) {
+    if (value == 0L || value == 1L) {
+      methodvisitor.visitInsn(Opcodes.LCONST_0 + (int) value);
+    } else {
+      methodvisitor.visitLdcInsn(new Long(value));
+    }
+  }
+
+  public void push(final float value) {
+    int bits = Float.floatToIntBits(value);
+    if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
+      methodvisitor.visitInsn(Opcodes.FCONST_0 + (int) value);
+    } else {
+      methodvisitor.visitLdcInsn(new Float(value));
+    }
+  }
+
+  public void push(final double value) {
+    long bits = Double.doubleToLongBits(value);
+    if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
+      methodvisitor.visitInsn(Opcodes.DCONST_0 + (int) value);
+    } else {
+      methodvisitor.visitLdcInsn(new Double(value));
+    }
+  }
+
+  public void push(final String value) {
+    Preconditions.checkNotNull(value);
+    methodvisitor.visitLdcInsn(value);
+  }
+
+  public void ifCmp(TajoDataTypes.DataType dataType, EvalType evalType, Label 
elseLabel) {
+
+    if (isJVMInternalInt(dataType)) {
+      switch (evalType) {
+      case EQUAL:
+        methodvisitor.visitJumpInsn(Opcodes.IF_ICMPNE, elseLabel);
+        break;
+      case NOT_EQUAL:
+        methodvisitor.visitJumpInsn(Opcodes.IF_ICMPEQ, elseLabel);
+        break;
+      case LTH:
+        methodvisitor.visitJumpInsn(Opcodes.IF_ICMPGE, elseLabel);
+        break;
+      case LEQ:
+        methodvisitor.visitJumpInsn(Opcodes.IF_ICMPGT, elseLabel);
+        break;
+      case GTH:
+        methodvisitor.visitJumpInsn(Opcodes.IF_ICMPLE, elseLabel);
+        break;
+      case GEQ:
+        methodvisitor.visitJumpInsn(Opcodes.IF_ICMPLT, elseLabel);
+        break;
+      default:
+        throw new CompilationError("Unknown comparison operator: " + 
evalType.name());
+      }
+    } else {
+
+      if (dataType.getType() == TEXT) {
+        invokeVirtual(String.class, "compareTo", int.class, new 
Class[]{String.class});
+      } else {
+        int opCode = TajoGeneratorAdapter.getOpCode(evalType, dataType);
+        methodvisitor.visitInsn(opCode);
+      }
+
+      switch (evalType) {
+      case EQUAL:
+        methodvisitor.visitJumpInsn(Opcodes.IFNE, elseLabel);
+        break;
+      case NOT_EQUAL:
+        methodvisitor.visitJumpInsn(Opcodes.IFEQ, elseLabel);
+        break;
+      case LTH:
+        methodvisitor.visitJumpInsn(Opcodes.IFGE, elseLabel);
+        break;
+      case LEQ:
+        methodvisitor.visitJumpInsn(Opcodes.IFGT, elseLabel);
+        break;
+      case GTH:
+        methodvisitor.visitJumpInsn(Opcodes.IFLE, elseLabel);
+        break;
+      case GEQ:
+        methodvisitor.visitJumpInsn(Opcodes.IFLT, elseLabel);
+        break;
+      default:
+        throw new CompilationError("Unknown comparison operator: " + 
evalType.name());
+      }
+    }
+  }
+
+  public void load(TajoDataTypes.DataType dataType, int idx) {
+    switch (dataType.getType()) {
+    case NULL_TYPE:
+    case BOOLEAN:
+    case CHAR:
+    case INT1:
+    case INT2:
+    case INT4:
+    case INET4:
+      methodvisitor.visitVarInsn(Opcodes.ILOAD, idx);
+      break;
+    case INT8:
+      methodvisitor.visitVarInsn(Opcodes.LLOAD, idx);
+      break;
+    case FLOAT4:
+      methodvisitor.visitVarInsn(Opcodes.FLOAD, idx);
+      break;
+    case FLOAT8:
+      methodvisitor.visitVarInsn(Opcodes.DLOAD, idx);
+      break;
+    case TEXT:
+    case INTERVAL:
+    case PROTOBUF:
+      methodvisitor.visitVarInsn(Opcodes.ALOAD, idx);
+      break;
+    default:
+      throw new CompilationError("Unknown data type: " + 
dataType.getType().name());
+    }
+  }
+
+  public static String getDescription(Class clazz) {
+    if (clazz == null) {
+      return "";
+    } else if (clazz == void.class) {
+      return "V";
+    } else if (clazz == boolean.class) {
+      return "Z";
+    } else if (clazz == char.class) {
+      return "C";
+    } else if (clazz == byte.class) {
+      return "B";
+    } else if (clazz == short.class) {
+      return "S";
+    } else if (clazz == int.class) {
+      return "I";
+    } else if (clazz == long.class) {
+      return "J";
+    } else if (clazz == float.class) {
+      return "F";
+    } else if (clazz == double.class) {
+      return "D";
+    } else if (clazz.isArray()) {
+      return "[" + getDescription(clazz.getComponentType());
+    } else {
+      return "L" + getInternalName(clazz) + ";";
+    }
+  }
+
+  public static String getMethodDescription(Class returnType, Class [] 
argumentTypes) {
+    StringBuilder builder = new StringBuilder();
+    builder.append("(");
+    if (argumentTypes != null) {
+      for (Class argType : argumentTypes) {
+        builder.append(getDescription(argType));
+      }
+    }
+    builder.append(")");
+
+    builder.append(getDescription(returnType));
+    return builder.toString();
+  }
+
+  public Label newLabel() {
+    return new Label();
+  }
+
+  public void gotoLabel(Label label) {
+    methodvisitor.visitJumpInsn(Opcodes.GOTO, label);
+  }
+
+  public void pushBooleanOfThreeValuedLogic(boolean value) {
+    push(value ? 1 : 2); // TRUE or FALSE
+  }
+
+  public void pushNullOfThreeValuedLogic() {
+    push(0); // NULL of three valued logic
+  }
+
+  public void pushNullFlag(boolean trueIfNotNull) {
+    push(trueIfNotNull ? true : false);
+  }
+
+  public void emitNullityCheck(Label ifNull) {
+    methodvisitor.visitJumpInsn(Opcodes.IFEQ, ifNull);
+  }
+
+  /**
+   * If at least one of all local variables corresponding to 
<code>varIds</code> is null, jump the <code>label</code>.
+   *
+   * @param ifNull The label to jump
+   * @param varIds A list of variable Ids.
+   */
+  public void emitNullityCheck(Label ifNull, int ... varIds) {
+    // TODO - ANDing can be reduced if we interleave IAND into a sequence of 
ILOAD instructions.
+    for (int varId : varIds) {
+      methodvisitor.visitVarInsn(Opcodes.ILOAD, varId);
+    }
+    if (varIds.length > 1) {
+      for (int i = 0; i < varIds.length - 1; i++) {
+        methodvisitor.visitInsn(Opcodes.IAND);
+      }
+    }
+    emitNullityCheck(ifNull);
+  }
+
+  public void pushDummyValue(TajoDataTypes.DataType type) {
+    if (type.getType() == NULL_TYPE) {
+      pushNullOfThreeValuedLogic();
+    } else if (isJVMInternalInt(type) || type.getType() == DATE) {
+      push(0);
+    } else if (type.getType() == TajoDataTypes.Type.INT8 || type.getType() == 
TIMESTAMP || type.getType() == TIME) {
+      push(0L);
+    } else if (type.getType() == TajoDataTypes.Type.FLOAT8) {
+      push(0.0d);
+    } else if (type.getType() == TajoDataTypes.Type.FLOAT4) {
+      push(0.0f);
+    } else if (type.getType() == TajoDataTypes.Type.CHAR || type.getType() == 
TajoDataTypes.Type.TEXT) {
+      push("");
+    } else if (type.getType() == INTERVAL || type.getType() == PROTOBUF) {
+      invokeStatic(NullDatum.class, "get", NullDatum.class, new Class[]{});
+    } else {
+      assert false;
+    }
+  }
+
+  public void newInstance(Class owner, Class [] paramTypes) {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, 
getInternalName(owner), "<init>",
+        getMethodDescription(void.class, paramTypes));
+  }
+
+  public void invokeSpecial(Class owner, String methodName, Class returnType, 
Class [] paramTypes) {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, 
getInternalName(owner), methodName,
+        getMethodDescription(returnType, paramTypes));
+  }
+
+  public void invokeStatic(Class owner, String methodName, Class returnType, 
Class [] paramTypes) {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
getInternalName(owner), methodName,
+        getMethodDescription(returnType, paramTypes));
+  }
+
+  public void invokeVirtual(Class owner, String methodName, Class returnType, 
Class [] paramTypes) {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, 
Type.getInternalName(owner), methodName,
+        getMethodDescription(returnType, paramTypes));
+  }
+
+  public void invokeInterface(Class owner, String methodName, Class 
returnType, Class [] paramTypes) {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, 
Type.getInternalName(owner), methodName,
+        getMethodDescription(returnType, paramTypes));
+  }
+
+  public static boolean isPrimitiveOpCode(EvalType evalType, 
TajoDataTypes.DataType returnType) {
+    return TUtil.containsInNestedMap(OpCodesMap, evalType, 
returnType.getType());
+  }
+
+  public static int getOpCode(EvalType evalType, TajoDataTypes.DataType 
returnType) {
+    if (!isPrimitiveOpCode(evalType, returnType)) {
+      throw new CompilationError("No Such OpCode for " + evalType + " 
returning " + returnType.getType().name());
+    }
+    return TUtil.getFromNestedMap(OpCodesMap, evalType, returnType.getType());
+  }
+
+  public void castInsn(TajoDataTypes.DataType srcType, TajoDataTypes.DataType 
targetType) {
+    TajoDataTypes.Type srcRawType = srcType.getType();
+    TajoDataTypes.Type targetRawType = targetType.getType();
+    switch(srcRawType) {
+    case BOOLEAN:
+    case CHAR: {
+      if (srcType.hasLength() && srcType.getLength() == 1) {
+        switch (targetType.getType()) {
+        case CHAR:
+        case INT1:
+        case INT2:
+        case INT4: break;
+        case INT8:   methodvisitor.visitInsn(Opcodes.I2L); break;
+        case FLOAT4: methodvisitor.visitInsn(Opcodes.I2F); break;
+        case FLOAT8: methodvisitor.visitInsn(Opcodes.I2D); break;
+        case TEXT:   emitStringValueOfChar(); break;
+        default:
+          throw new InvalidCastException(srcType, targetType);
+        }
+      } else {
+        switch (targetRawType) {
+        case CHAR:
+        case INT1:
+        case INT2:
+        case INT4: emitParseInt4(); break;
+        case INT8: emitParseInt8(); break;
+        case FLOAT4: emitParseFloat4(); break;
+        case FLOAT8: emitParseFloat8(); break;
+        case TEXT: break;
+        default: throw new InvalidCastException(srcType, targetType);
+        }
+      }
+      break;
+    }
+    case INT1:
+    case INT2:
+    case INT4:
+      switch (targetType.getType()) {
+      case CHAR:
+      case INT1: methodvisitor.visitInsn(Opcodes.I2C); break;
+      case INT2: methodvisitor.visitInsn(Opcodes.I2S); break;
+      case INT4: return;
+      case INT8: methodvisitor.visitInsn(Opcodes.I2L); break;
+      case FLOAT4: methodvisitor.visitInsn(Opcodes.I2F); break;
+      case FLOAT8: methodvisitor.visitInsn(Opcodes.I2D); break;
+      case TEXT: emitStringValueOfInt4(); break;
+      default: throw new InvalidCastException(srcType, targetType);
+      }
+      break;
+    case INT8:
+      switch (targetRawType) {
+      case CHAR:
+      case INT1:
+      case INT2:
+      case INT4: methodvisitor.visitInsn(Opcodes.L2I); break;
+      case INT8: return;
+      case FLOAT4: methodvisitor.visitInsn(Opcodes.L2F); break;
+      case FLOAT8: methodvisitor.visitInsn(Opcodes.L2D); break;
+      case TEXT: emitStringValueOfInt8(); break;
+      default: throw new InvalidCastException(srcType, targetType);
+      }
+      break;
+    case FLOAT4:
+      switch (targetRawType) {
+      case CHAR:
+      case INT1:
+      case INT2:
+      case INT4: methodvisitor.visitInsn(Opcodes.F2I); break;
+      case INT8: methodvisitor.visitInsn(Opcodes.F2L); break;
+      case FLOAT4: return;
+      case FLOAT8: methodvisitor.visitInsn(Opcodes.F2D); break;
+      case TEXT: emitStringValueOfFloat4(); break;
+      default: throw new InvalidCastException(srcType, targetType);
+      }
+      break;
+    case FLOAT8:
+      switch (targetRawType) {
+      case CHAR:
+      case INT1:
+      case INT2:
+      case INT4: methodvisitor.visitInsn(Opcodes.D2I); break;
+      case INT8: methodvisitor.visitInsn(Opcodes.D2L); break;
+      case FLOAT4: methodvisitor.visitInsn(Opcodes.D2F); break;
+      case FLOAT8: return;
+      case TEXT: emitStringValueOfFloat8(); break;
+      default: throw new InvalidCastException(srcType, targetType);
+      }
+      break;
+    case TEXT:
+      switch (targetRawType) {
+      case CHAR:
+      case INT1:
+      case INT2:
+      case INT4: emitParseInt4(); break;
+      case INT8: emitParseInt8(); break;
+      case FLOAT4: emitParseFloat4(); break;
+      case FLOAT8: emitParseFloat8(); break;
+      case TEXT: break;
+      case TIMESTAMP: {
+        methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(DateTimeUtil.class),
+            "toJulianTimestampWithTZ", "(L" + 
Type.getInternalName(String.class) + ";)J");
+        break;
+      }
+      case DATE: {
+        methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(DateTimeUtil.class),
+            "toJulianDate", "(L" + Type.getInternalName(String.class) + ";)I");
+        break;
+      }
+      case TIME: {
+        methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(DateTimeUtil.class),
+            "toJulianTime", "(L" + Type.getInternalName(String.class) + ";)J");
+        break;
+      }
+      default: throw new InvalidCastException(srcType, targetType);
+      }
+      break;
+    default: throw new InvalidCastException(srcType, targetType);
+    }
+  }
+
+  public static String getInternalName(String className) {
+    return className.replace('.', '/');
+  }
+
+  public static String getInternalName(Class clazz) {
+    return clazz.getName().replace('.', '/');
+  }
+
+  public void convertToPrimitive(TajoDataTypes.DataType type) {
+
+    Label ifNull = new Label();
+    Label afterAll = new Label();
+
+    // datum
+    int datum = astore();
+
+    aload(datum);
+    invokeVirtual(Datum.class, "isNotNull", boolean.class, new Class [] {});
+    methodvisitor.visitJumpInsn(Opcodes.IFEQ, ifNull);  // datum
+
+    aload(datum);
+    switch (type.getType()) {
+    case BOOLEAN:
+    case INT1:
+    case INT2:
+      invokeVirtual(Datum.class, "asInt2", short.class, new Class[] {});
+      break;
+    case INT4:
+    case DATE:
+      invokeVirtual(Datum.class, "asInt4", int.class, new Class[] {});
+      break;
+    case INT8:
+    case TIMESTAMP:
+    case TIME:
+      invokeVirtual(Datum.class, "asInt8", long.class, new Class[] {});
+      break;
+    case FLOAT4:
+      invokeVirtual(Datum.class, "asFloat4", float.class, new Class[] {});
+      break;
+    case FLOAT8:
+      invokeVirtual(Datum.class, "asFloat8", double.class, new Class[] {});
+      break;
+    case CHAR:
+    case TEXT:
+      invokeVirtual(Datum.class, "asChars", String.class, new Class[]{});
+      break;
+    default:
+      throw new UnsupportedException("Unsupported type: " + type);
+    }
+
+    pushNullFlag(true);
+    gotoLabel(afterAll);
+
+    methodvisitor.visitLabel(ifNull);
+    pushDummyValue(type);
+    pushNullFlag(false);
+
+    methodvisitor.visitLabel(afterAll);
+  }
+
+  public void convertToDatum(TajoDataTypes.DataType type, boolean castToDatum) 
{
+    String convertMethod;
+    Class returnType;
+    Class [] paramTypes;
+    switch (type.getType()) {
+    case NULL_TYPE:
+      pop();      // pop null flag
+      pop(type);  // pop null datum
+      invokeStatic(NullDatum.class, "get", NullDatum.class, new Class[] {});
+      if (castToDatum) {
+        methodvisitor.visitTypeInsn(Opcodes.CHECKCAST, 
getInternalName(Datum.class));
+      }
+      return;
+
+    case BOOLEAN:
+      convertMethod = "createBool";
+      returnType = Datum.class;
+      paramTypes = new Class[] {int.class};
+      break;
+    case CHAR:
+      convertMethod = "createChar";
+      returnType = CharDatum.class;
+      paramTypes = new Class[] {String.class};
+      break;
+    case INT1:
+    case INT2:
+      convertMethod = "createInt2";
+      returnType = Int2Datum.class;
+      paramTypes = new Class[] {short.class};
+      break;
+    case INT4:
+      convertMethod = "createInt4";
+      returnType = Int4Datum.class;
+      paramTypes = new Class[] {int.class};
+      break;
+    case INT8:
+      convertMethod = "createInt8";
+      returnType = Int8Datum.class;
+      paramTypes = new Class[] {long.class};
+      break;
+    case FLOAT4:
+      convertMethod = "createFloat4";
+      returnType = Float4Datum.class;
+      paramTypes = new Class[] {float.class};
+      break;
+    case FLOAT8:
+      convertMethod = "createFloat8";
+      returnType = Float8Datum.class;
+      paramTypes = new Class[] {double.class};
+      break;
+    case TEXT:
+      convertMethod = "createText";
+      returnType = TextDatum.class;
+      paramTypes = new Class[] {String.class};
+      break;
+    case TIMESTAMP:
+      convertMethod = "createTimestamp";
+      returnType = TimestampDatum.class;
+      paramTypes = new Class[] {long.class};
+      break;
+    case DATE:
+      convertMethod = "createDate";
+      returnType = DateDatum.class;
+      paramTypes = new Class[] {int.class};
+      break;
+    case TIME:
+      convertMethod = "createTime";
+      returnType = TimeDatum.class;
+      paramTypes = new Class[] {long.class};
+      break;
+    case INTERVAL:
+    case PROTOBUF:
+      convertMethod = null;
+      returnType = null;
+      paramTypes = null;
+      break;
+    case INET4:
+      convertMethod = "createInet4";
+      returnType = Inet4Datum.class;
+      paramTypes = new Class[] {int.class};
+      break;
+    default:
+      throw new RuntimeException("Unsupported type: " + type.getType().name());
+    }
+
+    Label ifNull = new Label();
+    Label afterAll = new Label();
+
+    emitNullityCheck(ifNull);
+    if (convertMethod != null) {
+      invokeStatic(DatumFactory.class, convertMethod, returnType, paramTypes);
+    }
+    methodvisitor.visitJumpInsn(Opcodes.GOTO, afterAll);
+
+    methodvisitor.visitLabel(ifNull);
+    pop(type);
+    invokeStatic(NullDatum.class, "get", NullDatum.class, null);
+
+    methodvisitor.visitLabel(afterAll);
+    if (castToDatum) {
+      methodvisitor.visitTypeInsn(Opcodes.CHECKCAST, 
TajoGeneratorAdapter.getInternalName(Datum.class));
+    }
+  }
+
+  public void pop(TajoDataTypes.DataType type) {
+    if (getWordSize(type) == 2) {
+      methodvisitor.visitInsn(Opcodes.POP2);
+    } else {
+      methodvisitor.visitInsn(Opcodes.POP);
+    }
+  }
+
+  public void emitStringValueOfChar() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(String.class),
+        "valueOf", "(C)L" + Type.getInternalName(String.class) + ";");
+  }
+
+  public void emitStringValueOfInt4() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(String.class),
+        "valueOf", "(I)L" + Type.getInternalName(String.class) + ";");
+  }
+
+  public void emitStringValueOfInt8() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(String.class),
+        "valueOf", "(J)L" + Type.getInternalName(String.class) + ";");
+  }
+
+  public void emitStringValueOfFloat4() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(String.class),
+        "valueOf", "(F)L" + Type.getInternalName(String.class) + ";");
+  }
+
+  public void emitStringValueOfFloat8() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(String.class),
+        "valueOf", "(D)L" + Type.getInternalName(String.class) + ";");
+  }
+
+  public void emitParseInt4() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(Integer.class),
+        "parseInt", "(L" + Type.getInternalName(String.class) + ";)I");
+  }
+
+  public void emitParseInt8() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(Long.class),
+        "parseLong", "(L" + Type.getInternalName(String.class) + ";)J");
+  }
+
+  public void emitParseFloat4() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(Float.class),
+        "parseFloat", "(L" + Type.getInternalName(String.class) + ";)F");
+  }
+
+  public void emitParseFloat8() {
+    methodvisitor.visitMethodInsn(Opcodes.INVOKESTATIC, 
Type.getInternalName(Double.class),
+        "parseDouble", "(L" + Type.getInternalName(String.class) + ";)D");
+  }
+
+  public void newArray(final Class clazz) {
+    int typeCode;
+    if (clazz == boolean.class) {
+      typeCode = Opcodes.T_BOOLEAN;
+    } else if (clazz == char.class) {
+      typeCode = Opcodes.T_CHAR;
+    } else if (clazz == byte.class) {
+      typeCode = Opcodes.T_BYTE;
+    } else if (clazz == short.class) {
+      typeCode = Opcodes.T_SHORT;
+    } else if (clazz == int.class) {
+      typeCode = Opcodes.T_INT;
+    } else if (clazz == long.class) {
+      typeCode = Opcodes.T_LONG;
+    } else if (clazz == float.class) {
+      typeCode = Opcodes.T_FLOAT;
+    } else if (clazz == double.class) {
+      typeCode = Opcodes.T_DOUBLE;
+    } else {
+      methodvisitor.visitTypeInsn(Opcodes.ANEWARRAY, getInternalName(clazz));
+      return;
+    }
+
+    methodvisitor.visitIntInsn(Opcodes.NEWARRAY, typeCode);
+  }
+
+  private int nextVarId = 3;
+
+  private Map<String, Integer> localVariablesMap = new HashMap<String, 
Integer>();
+
+  public void astore(String name) {
+    if (localVariablesMap.containsKey(name)) {
+      int varId = localVariablesMap.get(name);
+      methodvisitor.visitVarInsn(Opcodes.ASTORE, varId);
+    } else {
+      int varId = nextVarId++;
+      methodvisitor.visitVarInsn(Opcodes.ASTORE, varId);
+      localVariablesMap.put(name, varId);
+    }
+  }
+
+  public int astore() {
+    int varId = getCurVarIdAndIncrease();
+    methodvisitor.visitVarInsn(Opcodes.ASTORE, varId);
+    return varId;
+  }
+
+  public void astore(int varId) {
+    methodvisitor.visitVarInsn(Opcodes.ASTORE, varId);
+  }
+
+  public void aload(String name) {
+    if (localVariablesMap.containsKey(name)) {
+      int varId = localVariablesMap.get(name);
+      methodvisitor.visitVarInsn(Opcodes.ALOAD, varId);
+    } else {
+      throw new RuntimeException("No such variable name: " + name);
+    }
+  }
+
+  public void aload(int varId) {
+    methodvisitor.visitVarInsn(Opcodes.ALOAD, varId);
+  }
+
+  public void dup() {
+    methodvisitor.visitInsn(Opcodes.DUP);
+  }
+
+  public void pop() {
+    methodvisitor.visitInsn(Opcodes.POP);
+  }
+
+  public void pop2() {
+    methodvisitor.visitInsn(Opcodes.POP2);
+  }
+
+  public int istore() {
+    int varId = getCurVarIdAndIncrease();
+    methodvisitor.visitVarInsn(Opcodes.ISTORE, varId);
+    return varId;
+  }
+
+  public void iload(int varId) {
+    methodvisitor.visitVarInsn(Opcodes.ILOAD, varId);
+  }
+
+  private int getCurVarIdAndIncrease() {
+    int varId = nextVarId++;
+    return varId;
+  }
+
+  private int getCurVarIdAndIncrease(TajoDataTypes.DataType type) {
+    int varId = nextVarId;
+    nextVarId += getWordSize(type);
+    return varId;
+  }
+
+  public int store(TajoDataTypes.DataType type) {
+    int varId = nextVarId;
+    nextVarId += TajoGeneratorAdapter.getWordSize(type);
+
+    switch (type.getType()) {
+    case NULL_TYPE:
+    case BOOLEAN:
+    case CHAR:
+    case INT1:
+    case INT2:
+    case INT4:
+    case INET4:
+      methodvisitor.visitVarInsn(Opcodes.ISTORE, varId);
+      break;
+    case TIME:
+    case TIMESTAMP:
+    case INT8:
+      methodvisitor.visitVarInsn(Opcodes.LSTORE, varId);
+      break;
+    case FLOAT4:
+      methodvisitor.visitVarInsn(Opcodes.FSTORE, varId);
+      break;
+    case FLOAT8:
+      methodvisitor.visitVarInsn(Opcodes.DSTORE, varId);
+      break;
+    case INTERVAL:
+    case TEXT:
+      methodvisitor.visitVarInsn(Opcodes.ASTORE, varId);
+      break;
+    default:
+      throw new CompilationError("Unknown data type: " + 
type.getType().name());
+    }
+
+    return varId;
+  }
+
+  public static interface SwitchCaseGenerator extends TableSwitchGenerator {
+    int size();
+    int min();
+    int max();
+    int key(int index);
+    void generateCase(int index, Label end);
+    void generateDefault();
+  }
+
+  public static class SwitchCase implements Comparable<SwitchCase> {
+    private final int index;
+    private final EvalNode thanResult;
+
+    public SwitchCase(int index, EvalNode thanResult) {
+      this.index = index;
+      this.thanResult = thanResult;
+    }
+
+    public int key() {
+      return index;
+    }
+
+    public EvalNode result() {
+      return thanResult;
+    }
+
+    @Override
+    public int compareTo(SwitchCase o) {
+      return index - o.index;
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
new file mode 100644
index 0000000..9f50bb5
--- /dev/null
+++ 
b/tajo-core/src/main/java/org/apache/tajo/engine/codegen/VariablesPreBuilder.java
@@ -0,0 +1,83 @@
+/*
+ * 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.tajo.engine.codegen;
+
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.IntervalDatum;
+import org.apache.tajo.engine.eval.*;
+import org.apache.tajo.org.objectweb.asm.Opcodes;
+
+import java.util.Stack;
+
+class VariablesPreBuilder extends SimpleEvalNodeVisitor<EvalCodeGenContext> {
+
+  public EvalNode visitBinaryEval(EvalCodeGenContext context, Stack<EvalNode> 
stack, BinaryEval binaryEval) {
+    super.visitBinaryEval(context, stack, binaryEval);
+
+    if (EvalType.isStringPatternMatchOperator(binaryEval.getType())) {
+      if (!context.symbols.containsKey(binaryEval)) {
+        String fieldName = binaryEval.getType().name() + "_" + context.seqId++;
+        context.symbols.put(binaryEval, fieldName);
+
+        Class clazz = 
EvalCodeGenerator.getStringPatternEvalClass(binaryEval.getType());
+        context.classWriter.visitField(Opcodes.ACC_PRIVATE, fieldName,
+            "L" + TajoGeneratorAdapter.getInternalName(clazz) + ";", null, 
null);
+      }
+    } else if (binaryEval.getType() == EvalType.IN) {
+      if (!context.symbols.containsKey(binaryEval)) {
+        String fieldName = binaryEval.getType().name() + "_" + context.seqId++;
+        context.symbols.put(binaryEval, fieldName);
+
+        context.classWriter.visitField(Opcodes.ACC_PRIVATE, fieldName,
+            "L" + TajoGeneratorAdapter.getInternalName(InEval.class) + ";", 
null, null);
+      }
+    }
+
+    return binaryEval;
+  }
+
+  @Override
+  public EvalNode visitConst(EvalCodeGenContext context, ConstEval constEval, 
Stack<EvalNode> stack) {
+
+    if (constEval.getValueType().getType() == TajoDataTypes.Type.INTERVAL) {
+      if (!context.symbols.containsKey(constEval)) {
+        String fieldName = constEval.getValueType().getType().name() + "_" + 
context.seqId++;
+        context.symbols.put(constEval, fieldName);
+
+        context.classWriter.visitField(Opcodes.ACC_PRIVATE, fieldName,
+            "L" + TajoGeneratorAdapter.getInternalName(IntervalDatum.class) + 
";", null, null);
+      }
+    }
+    return constEval;
+  }
+
+  @Override
+  public EvalNode visitFuncCall(EvalCodeGenContext context, FunctionEval 
function, Stack<EvalNode> stack) {
+    super.visitFuncCall(context, function, stack);
+
+    if (!context.symbols.containsKey(function)) {
+      String fieldName = function.getFuncDesc().getSignature() + "_" + 
context.seqId++;
+      context.symbols.put(function, fieldName);
+      context.classWriter.visitField(Opcodes.ACC_PRIVATE, fieldName,
+          "L" + 
TajoGeneratorAdapter.getInternalName(function.getFuncDesc().getFuncClass()) + 
";", null, null);
+    }
+
+    return function;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
index 4c94f4a..d7473e9 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
@@ -35,6 +35,7 @@ import static org.apache.tajo.common.TajoDataTypes.Type;
 public class BinaryEval extends EvalNode implements Cloneable {
   @Expose protected EvalNode leftExpr;
   @Expose protected EvalNode rightExpr;
+  @Expose protected DataType returnType;
 
   protected BinaryEval(EvalType type) {
     super(type);

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNode.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
index 48ab516..754f888 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
@@ -32,7 +32,6 @@ import org.apache.tajo.storage.Tuple;
  */
 public abstract class EvalNode implements Cloneable, GsonObject {
        @Expose protected EvalType type;
-  @Expose protected DataType returnType = null;
 
   public EvalNode() {
   }
@@ -70,7 +69,6 @@ public abstract class EvalNode implements Cloneable, 
GsonObject {
   public Object clone() throws CloneNotSupportedException {
     EvalNode evalNode = (EvalNode) super.clone();
     evalNode.type = type;
-    evalNode.returnType = returnType;
     return evalNode;
   }
 }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
index 0035636..457f651 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
@@ -43,12 +43,18 @@ public class EvalTreeUtil {
     node.postOrder(new ChangeColumnRefVisitor(oldName, newName));
   }
 
-  public static void replace(EvalNode expr, EvalNode targetExpr, EvalNode 
tobeReplaced) {
+  public static int replace(EvalNode expr, EvalNode targetExpr, EvalNode 
tobeReplaced) {
     EvalReplaceVisitor replacer = new EvalReplaceVisitor(targetExpr, 
tobeReplaced);
-    replacer.visitChild(null, expr, new Stack<EvalNode>());
+    ReplaceContext context = new ReplaceContext();
+    replacer.visitChild(context, expr, new Stack<EvalNode>());
+    return context.countOfReplaces;
   }
 
-  public static class EvalReplaceVisitor extends 
BasicEvalNodeVisitor<EvalNode, EvalNode> {
+  private static class ReplaceContext {
+    int countOfReplaces = 0;
+  }
+
+  public static class EvalReplaceVisitor extends 
BasicEvalNodeVisitor<ReplaceContext, EvalNode> {
     private EvalNode target;
     private EvalNode tobeReplaced;
 
@@ -58,10 +64,12 @@ public class EvalTreeUtil {
     }
 
     @Override
-    public EvalNode visitChild(EvalNode context, EvalNode evalNode, 
Stack<EvalNode> stack) {
+    public EvalNode visitChild(ReplaceContext context, EvalNode evalNode, 
Stack<EvalNode> stack) {
       super.visitChild(context, evalNode, stack);
 
       if (evalNode.equals(target)) {
+        context.countOfReplaces++;
+
         EvalNode parent = stack.peek();
 
         if (parent instanceof BetweenPredicateEval) {

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalType.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalType.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalType.java
index 500928a..d533510 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalType.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalType.java
@@ -152,6 +152,16 @@ public enum EvalType {
     return match;
   }
 
+  public static boolean isStringPatternMatchOperator(EvalType type) {
+    boolean match = false;
+
+    match |= type == LIKE;
+    match |= type == SIMILAR_TO;
+    match |= type == REGEX;
+
+    return match;
+  }
+
   public String getOperatorName() {
     return operatorName != null ? operatorName : name();
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
index 9447ef2..5d358f7 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
@@ -47,6 +47,10 @@ public abstract class FunctionEval extends EvalNode 
implements Cloneable {
     this.argEvals = argEvals;
        }
 
+  public FunctionDesc getFuncDesc() {
+    return funcDesc;
+  }
+
   public ParamType [] getParamType() {
     ParamType [] paramTypes = new ParamType[argEvals.length];
     for (int i = 0; i < argEvals.length; i++) {
@@ -93,6 +97,7 @@ public abstract class FunctionEval extends EvalNode 
implements Cloneable {
     return argEvals[idx];
   }
 
+
        public DataType getValueType() {
                return this.funcDesc.getReturnType();
        }
@@ -105,10 +110,6 @@ public abstract class FunctionEval extends EvalNode 
implements Cloneable {
                return funcDesc.getSignature();
        }
 
-  public FunctionDesc getFuncDesc() {
-    return this.funcDesc;
-  }
-
   @Override
        public String toString() {
                StringBuilder sb = new StringBuilder();
@@ -117,7 +118,7 @@ public abstract class FunctionEval extends EvalNode 
implements Cloneable {
                        if(i+1 < argEvals.length)
                                sb.append(",");
                }
-               return funcDesc.getSignature() + "(" + (isDistinct() ? " 
distinct" : "") + sb+")";
+               return funcDesc.getSignature() + "(" + (isDistinct() ? " 
distinct " : "") + sb+")";
        }
        
        @Override

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
index bfac33e..535677f 100644
--- a/tajo-core/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
@@ -25,6 +25,10 @@ import java.util.regex.PatternSyntaxException;
 
 public class LikePredicateEval extends PatternMatchPredicateEval {
 
+  public LikePredicateEval(boolean not, EvalNode field, ConstEval pattern) {
+    super(EvalType.LIKE, not, field, pattern, false);
+  }
+
   public LikePredicateEval(boolean not, EvalNode field, ConstEval pattern, 
boolean caseSensitive) {
     super(EvalType.LIKE, not, field, pattern, caseSensitive);
   }

http://git-wip-us.apache.org/repos/asf/tajo/blob/7603a3d4/tajo-core/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
----------------------------------------------------------------------
diff --git 
a/tajo-core/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
index 8d78b0b..0a8e800 100644
--- 
a/tajo-core/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
+++ 
b/tajo-core/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
@@ -55,6 +55,14 @@ public abstract class PatternMatchPredicateEval extends 
BinaryEval {
 
   abstract void compile(String pattern) throws PatternSyntaxException;
 
+  public boolean isNot() {
+    return not;
+  }
+
+  public boolean isCaseInsensitive() {
+    return caseInsensitive;
+  }
+
   @Override
   public DataType getValueType() {
     return RES_TYPE;

Reply via email to