tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hyun...@apache.org
Subject [47/51] [partial] TAJO-752: Escalate sub modules in tajo-core into the top-level modules. (hyunsik)
Date Fri, 18 Apr 2014 09:20:09 GMT
http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..d362927
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/BinaryEval.java
@@ -0,0 +1,205 @@
+/**
+ * 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.eval;
+
+import com.google.common.base.Objects;
+import com.google.common.base.Preconditions;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
+
+import static org.apache.tajo.common.TajoDataTypes.Type;
+
+public class BinaryEval extends EvalNode implements Cloneable {
+  @Expose private DataType returnType = null;
+
+  /**
+   * @param type
+   */
+  public BinaryEval(EvalType type, EvalNode left, EvalNode right) {
+    super(type, left, right);
+    Preconditions.checkNotNull(type);
+    Preconditions.checkNotNull(left);
+    Preconditions.checkNotNull(right);
+
+    if(
+        type == EvalType.AND ||
+            type == EvalType.OR ||
+            type == EvalType.EQUAL ||
+            type == EvalType.NOT_EQUAL ||
+            type == EvalType.LTH ||
+            type == EvalType.GTH ||
+            type == EvalType.LEQ ||
+            type == EvalType.GEQ ) {
+      this.returnType = CatalogUtil.newSimpleDataType(Type.BOOLEAN);
+    } else if (
+        type == EvalType.PLUS ||
+            type == EvalType.MINUS ||
+            type == EvalType.MULTIPLY ||
+            type == EvalType.DIVIDE ||
+            type == EvalType.MODULAR ) {
+      this.returnType = determineType(left.getValueType(), right.getValueType());
+
+    } else if (type == EvalType.CONCATENATE) {
+      this.returnType = CatalogUtil.newSimpleDataType(Type.TEXT);
+    }
+  }
+
+  public BinaryEval(PartialBinaryExpr expr) {
+    this(expr.type, expr.leftExpr, expr.rightExpr);
+  }
+
+  /**
+   * This is verified by ExprsVerifier.checkArithmeticOperand().
+   */
+  private DataType determineType(DataType left, DataType right) throws InvalidEvalException {
+    switch (left.getType()) {
+    case INT4: {
+      switch(right.getType()) {
+      case INT2:
+      case INT4: return CatalogUtil.newSimpleDataType(Type.INT4);
+      case INT8: return CatalogUtil.newSimpleDataType(Type.INT8);
+      case FLOAT4: return CatalogUtil.newSimpleDataType(Type.FLOAT4);
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      }
+    }
+
+    case INT8: {
+      switch(right.getType()) {
+      case INT2:
+      case INT4:
+      case INT8: return CatalogUtil.newSimpleDataType(Type.INT8);
+      case FLOAT4:
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      }
+    }
+
+    case FLOAT4: {
+      switch(right.getType()) {
+      case INT2:
+      case INT4:
+      case INT8:
+      case FLOAT4:
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      }
+    }
+
+    case FLOAT8: {
+      switch(right.getType()) {
+      case INT2:
+      case INT4:
+      case INT8:
+      case FLOAT4:
+      case FLOAT8: return CatalogUtil.newSimpleDataType(Type.FLOAT8);
+      }
+    }
+
+    default: return left;
+    }
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    Datum lhs = leftExpr.eval(schema, tuple);
+    Datum rhs = rightExpr.eval(schema, tuple);
+
+    switch(type) {
+    case AND:
+      return lhs.and(rhs);
+    case OR:
+      return lhs.or(rhs);
+
+    case EQUAL:
+      return lhs.equalsTo(rhs);
+    case NOT_EQUAL:
+      return lhs.notEqualsTo(rhs);
+    case LTH:
+      return lhs.lessThan(rhs);
+    case LEQ:
+      return lhs.lessThanEqual(rhs);
+    case GTH:
+      return lhs.greaterThan(rhs);
+    case GEQ:
+      return lhs.greaterThanEqual(rhs);
+
+    case PLUS:
+      return lhs.plus(rhs);
+    case MINUS:
+      return lhs.minus(rhs);
+    case MULTIPLY:
+      return lhs.multiply(rhs);
+    case DIVIDE:
+      return lhs.divide(rhs);
+    case MODULAR:
+      return lhs.modular(rhs);
+
+    case CONCATENATE:
+      if (lhs.type() == Type.NULL_TYPE || rhs.type() == Type.NULL_TYPE) {
+        return NullDatum.get();
+      }
+      return DatumFactory.createText(lhs.asChars() + rhs.asChars());
+    default:
+      throw new InvalidEvalException("We does not support " + type + " expression yet");
+    }
+  }
+
+  @Override
+	public String getName() {
+		return type.name();
+	}
+
+	@Override
+	public DataType getValueType() {
+	  return returnType;
+	}
+
+	public String toString() {
+		return leftExpr +" " + type.getOperatorName() + " "+rightExpr;
+	}
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof BinaryEval) {
+      BinaryEval other = (BinaryEval) obj;
+
+      boolean b1 = this.type == other.type;
+      boolean b2 = leftExpr.equals(other.leftExpr);
+      boolean b3 = rightExpr.equals(other.rightExpr);
+      return b1 && b2 && b3;
+    }
+    return false;
+  }
+
+  public int hashCode() {
+    return Objects.hashCode(this.type, leftExpr, rightExpr);
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    BinaryEval eval = (BinaryEval) super.clone();
+    eval.returnType = returnType;
+
+    return eval;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
new file mode 100644
index 0000000..d08bfd3
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/CaseWhenEval.java
@@ -0,0 +1,208 @@
+/**
+ * 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.eval;
+
+import com.google.common.collect.Lists;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.util.TUtil;
+
+import java.util.List;
+
+public class CaseWhenEval extends EvalNode implements GsonObject {
+  @Expose private List<IfThenEval> whens = Lists.newArrayList();
+  @Expose private EvalNode elseResult;
+
+  public CaseWhenEval() {
+    super(EvalType.CASE);
+  }
+
+  public void addWhen(EvalNode condition, EvalNode result) {
+    whens.add(new IfThenEval(condition, result));
+  }
+
+  public List<IfThenEval> getIfThenEvals() {
+    return whens;
+  }
+
+  public boolean hasElse() {
+    return this.elseResult != null;
+  }
+
+  public EvalNode getElse() {
+    return elseResult;
+  }
+
+  public void setElseResult(EvalNode elseResult) {
+    this.elseResult = elseResult;
+  }
+
+  @Override
+  public DataType getValueType() {
+    return whens.get(0).getResultExpr().getValueType();
+  }
+
+  @Override
+  public String getName() {
+    return "?";
+  }
+
+  public Datum eval(Schema schema, Tuple tuple) {
+    for (int i = 0; i < whens.size(); i++) {
+      if (whens.get(i).checkIfCondition(schema, tuple)) {
+        return whens.get(i).eval(schema, tuple);
+      }
+    }
+
+    if (elseResult != null) { // without else clause
+      return elseResult.eval(schema, tuple);
+    }
+
+    return NullDatum.get();
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder sb = new StringBuilder("CASE ");
+    for (IfThenEval when : whens) {
+     sb.append(when).append(" ");
+    }
+
+    sb.append("ELSE ").append(elseResult).append(" END");
+
+    return sb.toString();
+  }
+
+  @Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+    for (IfThenEval when : whens) {
+      when.preOrder(visitor);
+    }
+    if (elseResult != null) { // without else clause
+      elseResult.preOrder(visitor);
+    }
+  }
+
+  @Override
+  public void postOrder(EvalNodeVisitor visitor) {
+    for (IfThenEval when : whens) {
+      when.postOrder(visitor);
+    }
+    if (elseResult != null) { // without else clause
+      elseResult.postOrder(visitor);
+    }
+    visitor.visit(this);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof CaseWhenEval) {
+      CaseWhenEval other = (CaseWhenEval) obj;
+
+      for (int i = 0; i < other.whens.size(); i++) {
+        if (!whens.get(i).equals(other.whens.get(i))) {
+          return false;
+        }
+      }
+      return TUtil.checkEquals(elseResult, other.elseResult);
+    } else {
+      return false;
+    }
+  }
+
+  public static class IfThenEval extends EvalNode implements GsonObject {
+    @Expose private EvalNode condition;
+    @Expose private EvalNode result;
+
+    public IfThenEval(EvalNode condition, EvalNode result) {
+      super(EvalType.IF_THEN);
+      this.condition = condition;
+      this.result = result;
+    }
+
+    @Override
+    public DataType getValueType() {
+      return CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+    }
+
+    @Override
+    public String getName() {
+      return "when?";
+    }
+
+    public boolean checkIfCondition(Schema schema, Tuple tuple) {
+      return condition.eval(schema, tuple).isTrue();
+    }
+
+    public Datum eval(Schema schema, Tuple tuple) {
+      return result.eval(schema, tuple);
+    }
+
+    public EvalNode getConditionExpr() {
+      return this.condition;
+    }
+
+    public EvalNode getResultExpr() {
+      return this.result;
+    }
+
+    @Override
+    public boolean equals(Object object) {
+      if (object instanceof IfThenEval) {
+        IfThenEval other = (IfThenEval) object;
+        return condition.equals(other.condition) && result.equals(other.result);
+      } else {
+        return false;
+      }
+    }
+
+    @Override
+    public String toString() {
+      return "WHEN " + condition + " THEN " + result;
+    }
+
+    @Override
+    public String toJson() {
+      return CoreGsonHelper.toJson(IfThenEval.this, IfThenEval.class);
+    }
+
+    @Override
+    public void preOrder(EvalNodeVisitor visitor) {
+      visitor.visit(this);
+      condition.preOrder(visitor);
+      result.preOrder(visitor);
+    }
+
+    @Override
+    public void postOrder(EvalNodeVisitor visitor) {
+      condition.postOrder(visitor);
+      result.postOrder(visitor);
+      visitor.visit(this);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/CastEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/CastEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/CastEval.java
new file mode 100644
index 0000000..a024b01
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/CastEval.java
@@ -0,0 +1,87 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.storage.Tuple;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+
+public class CastEval extends EvalNode {
+  @Expose private EvalNode operand;
+  @Expose private DataType target;
+
+  public CastEval(EvalNode operand, DataType target) {
+    super(EvalType.CAST);
+    this.operand = operand;
+    this.target = target;
+  }
+
+  public EvalNode getOperand() {
+    return operand;
+  }
+
+  @Override
+  public DataType getValueType() {
+    return target;
+  }
+
+  @Override
+  public String getName() {
+    return target.getType().name();
+  }
+
+  public Datum eval(Schema schema, Tuple tuple) {
+    Datum operandDatum = operand.eval(schema, tuple);
+    if (operandDatum.isNull()) {
+      return operandDatum;
+    }
+
+    return DatumFactory.cast(operandDatum, target);
+  }
+
+  public String toString() {
+    return "CAST (" + operand + " AS " + target.getType() + ")";
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    boolean valid = obj != null && obj instanceof CastEval;
+    if (valid) {
+      CastEval another = (CastEval) obj;
+      return operand.equals(another.operand) && target.equals(another.target);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+    operand.preOrder(visitor);
+  }
+
+  public void postOrder(EvalNodeVisitor visitor) {
+    operand.postOrder(visitor);
+    visitor.visit(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/ConstEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
new file mode 100644
index 0000000..2cb530d
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/ConstEval.java
@@ -0,0 +1,99 @@
+/**
+ * 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.eval;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.storage.Tuple;
+
+public class ConstEval extends EvalNode implements Comparable<ConstEval>, Cloneable {
+	@Expose Datum datum = null;
+	
+	public ConstEval(Datum datum) {
+		super(EvalType.CONST);
+		this.datum = datum;
+	}
+
+  public Datum getValue() {
+    return this.datum;
+  }
+	
+	public String toString() {
+		return datum.toString();
+	}
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    return datum;
+  }
+
+  @Override
+	public DataType getValueType() {
+    return CatalogUtil.newSimpleDataType(datum.type());
+	}
+
+	@Override
+	public String getName() {
+		return this.datum.toString();
+	}
+	
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof ConstEval) {
+      ConstEval other = (ConstEval) obj;
+
+      if (this.type == other.type && this.datum.equals(other.datum)) {
+        return true;
+      }
+    }
+    return false;
+  }
+  
+  @Override
+  public int hashCode() {
+    return Objects.hashCode(type, datum.type(), datum);
+  }
+  
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    ConstEval eval = (ConstEval) super.clone();
+    eval.datum = datum;
+    
+    return eval;
+  }
+
+  @Override
+  public int compareTo(ConstEval other) {    
+    return datum.compareTo(other.datum);
+  }
+  
+  @Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+  
+  @Override
+  public void postOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..1180bde
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNode.java
@@ -0,0 +1,118 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.json.CoreGsonHelper;
+import org.apache.tajo.json.GsonObject;
+import org.apache.tajo.storage.Tuple;
+
+/**
+ * An annotated expression which includes actual data domains.
+ * It is also used for evaluation.
+ */
+public abstract class EvalNode implements Cloneable, GsonObject {
+	@Expose protected EvalType type;
+	@Expose protected EvalNode leftExpr;
+	@Expose protected EvalNode rightExpr;
+	
+	public EvalNode(EvalType type) {
+		this.type = type;
+	}
+	
+	public EvalNode(EvalType type, EvalNode left, EvalNode right) {
+		this(type);
+		this.leftExpr = left;
+		this.rightExpr = right;
+	}
+	
+	public EvalType getType() {
+		return this.type;
+	}
+	
+	public void setLeftExpr(EvalNode expr) {
+		this.leftExpr = expr;
+	}
+	
+	public <T extends EvalNode> T getLeftExpr() {
+		return (T) this.leftExpr;
+	}
+	
+	public void setRightExpr(EvalNode expr) {
+		this.rightExpr = expr;
+	}
+	
+	public <T extends EvalNode> T getRightExpr() {
+		return (T) this.rightExpr;
+	}
+
+  public EvalNode getExpr(int id) {
+    if (id == 0) {
+      return this.leftExpr;
+    } else if (id == 1) {
+      return this.rightExpr;
+    } else {
+      throw new ArrayIndexOutOfBoundsException("only 0 or 1 is available (" + id + " is not available)");
+    }
+  }
+	
+	public abstract DataType getValueType();
+	
+	public abstract String getName();
+	
+	public String toString() {
+		return "(" + this.type + "(" + leftExpr.toString() + " " + rightExpr.toString() + "))";
+	}
+
+  @Override
+	public String toJson() {
+    return CoreGsonHelper.toJson(this, EvalNode.class);
+	}
+	
+	public abstract <T extends Datum> T eval(Schema schema, Tuple tuple);
+
+  @Deprecated
+	public void preOrder(EvalNodeVisitor visitor) {
+	  visitor.visit(this);
+	  leftExpr.preOrder(visitor);
+	  rightExpr.preOrder(visitor);
+	}
+
+  @Deprecated
+	public void postOrder(EvalNodeVisitor visitor) {
+	  leftExpr.postOrder(visitor);
+	  rightExpr.postOrder(visitor);	  	  
+	  visitor.visit(this);
+	}
+
+  public abstract boolean equals(Object obj);
+	
+	@Override
+	public Object clone() throws CloneNotSupportedException {
+	  EvalNode node = (EvalNode) super.clone();
+	  node.type = type;
+	  node.leftExpr = leftExpr != null ? (EvalNode) leftExpr.clone() : null;
+	  node.rightExpr = rightExpr != null ? (EvalNode) rightExpr.clone() : null;
+	  
+	  return node;
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
new file mode 100644
index 0000000..1680b31
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor.java
@@ -0,0 +1,24 @@
+/**
+ * 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.eval;
+
+@Deprecated
+public interface EvalNodeVisitor {
+  public void visit(EvalNode node);
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
new file mode 100644
index 0000000..024a988
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalNodeVisitor2.java
@@ -0,0 +1,71 @@
+/**
+ * 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.eval;
+
+import java.util.Stack;
+
+public interface EvalNodeVisitor2<CONTEXT, RESULT> {
+  RESULT visitChild(CONTEXT context, EvalNode evalNode, Stack<EvalNode> stack);
+
+  // Column and Value reference expressions
+  RESULT visitConst(CONTEXT context, ConstEval evalNode, Stack<EvalNode> stack);
+  RESULT visitRowConstant(CONTEXT context, RowConstantEval evalNode, Stack<EvalNode> stack);
+  RESULT visitField(CONTEXT context, Stack<EvalNode> stack, FieldEval evalNode);
+
+  // Arithmetic expression
+  RESULT visitPlus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitMinus(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitMultiply(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitDivide(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitModular(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+
+  // Logical Predicates
+  RESULT visitAnd(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitOr(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitNot(CONTEXT context, NotEval evalNode, Stack<EvalNode> stack);
+
+  // Comparison Predicates
+  RESULT visitEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitNotEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitLessThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitLessThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitGreaterThan(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+  RESULT visitGreaterThanOrEqual(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+
+  // Other Predicates
+  RESULT visitIsNull(CONTEXT context, IsNullEval evalNode, Stack<EvalNode> stack);
+  RESULT visitBetween(CONTEXT context, BetweenPredicateEval evalNode, Stack<EvalNode> stack);
+  RESULT visitCaseWhen(CONTEXT context, CaseWhenEval evalNode, Stack<EvalNode> stack);
+  RESULT visitIfThen(CONTEXT context, CaseWhenEval.IfThenEval evalNode, Stack<EvalNode> stack);
+  RESULT visitInPredicate(CONTEXT context, InEval evalNode, Stack<EvalNode> stack);
+
+  // String operator and Pattern matching predicates
+  RESULT visitLike(CONTEXT context, LikePredicateEval evalNode, Stack<EvalNode> stack);
+  RESULT visitSimilarTo(CONTEXT context, SimilarToPredicateEval evalNode, Stack<EvalNode> stack);
+  RESULT visitRegex(CONTEXT context, RegexPredicateEval evalNode, Stack<EvalNode> stack);
+  RESULT visitConcatenate(CONTEXT context, BinaryEval evalNode, Stack<EvalNode> stack);
+
+  // Functions
+  RESULT visitFuncCall(CONTEXT context, GeneralFunctionEval evalNode, Stack<EvalNode> stack);
+  RESULT visitAggrFuncCall(CONTEXT context, AggregationFunctionCallEval evalNode, Stack<EvalNode> stack);
+
+  RESULT visitSigned(CONTEXT context, SignedEval signedEval, Stack<EvalNode> stack);
+
+  RESULT visitCast(CONTEXT context, CastEval signedEval, Stack<EvalNode> stack);
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeFactory.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeFactory.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeFactory.java
new file mode 100644
index 0000000..aa72f25
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeFactory.java
@@ -0,0 +1,32 @@
+/**
+ * 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.eval;
+
+import org.apache.tajo.datum.Datum;
+
+public class EvalTreeFactory {
+	public static ConstEval newConst(Datum datum) {
+		return new ConstEval(datum);
+	}
+	
+	public static BinaryEval create(EvalType type, EvalNode e1,
+	    EvalNode e2) {
+		return new BinaryEval(type, e1, e2);
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..7dcc26a
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalTreeUtil.java
@@ -0,0 +1,350 @@
+/**
+ * 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.eval;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.planner.Target;
+import org.apache.tajo.exception.InternalException;
+import org.apache.tajo.util.TUtil;
+
+import java.util.*;
+
+public class EvalTreeUtil {
+
+  public static void changeColumnRef(EvalNode node, String oldName, String newName) {
+    node.postOrder(new ChangeColumnRefVisitor(oldName, newName));
+  }
+
+  public static void replace(EvalNode expr, EvalNode targetExpr, EvalNode tobeReplaced) {
+    EvalReplaceVisitor replacer = new EvalReplaceVisitor(targetExpr, tobeReplaced);
+    replacer.visitChild(null, expr, new Stack<EvalNode>());
+  }
+
+  public static class EvalReplaceVisitor extends BasicEvalNodeVisitor<EvalNode, EvalNode> {
+    private EvalNode target;
+    private EvalNode tobeReplaced;
+
+    public EvalReplaceVisitor(EvalNode target, EvalNode tobeReplaced) {
+      this.target = target;
+      this.tobeReplaced = tobeReplaced;
+    }
+
+    @Override
+    public EvalNode visitChild(EvalNode context, EvalNode evalNode, Stack<EvalNode> stack) {
+      super.visitChild(context, evalNode, stack);
+
+      if (evalNode.equals(target)) {
+        EvalNode parent = stack.peek();
+
+        if (parent.getLeftExpr().equals(evalNode)) {
+          parent.setLeftExpr(tobeReplaced);
+        }
+        if (parent.getRightExpr().equals(evalNode)) {
+          parent.setRightExpr(tobeReplaced);
+        }
+      }
+
+      return evalNode;
+    }
+  }
+
+  /**
+   * It finds unique columns from a EvalNode.
+   */
+  public static LinkedHashSet<Column> findUniqueColumns(EvalNode node) {
+    UniqueColumnFinder finder = new UniqueColumnFinder();
+    node.postOrder(finder);
+    return finder.getColumnRefs();
+  }
+  
+  public static List<Column> findAllColumnRefs(EvalNode node) {
+    AllColumnRefFinder finder = new AllColumnRefFinder();
+    node.postOrder(finder);
+    return finder.getColumnRefs();
+  }
+  
+  public static Schema getSchemaByTargets(Schema inputSchema, Target [] targets) 
+      throws InternalException {
+    Schema schema = new Schema();
+    for (Target target : targets) {
+      schema.addColumn(
+          target.hasAlias() ? target.getAlias() : target.getEvalTree().getName(),
+          getDomainByExpr(inputSchema, target.getEvalTree()));
+    }
+    
+    return schema;
+  }
+  
+  public static DataType getDomainByExpr(Schema inputSchema, EvalNode expr)
+      throws InternalException {
+    switch (expr.getType()) {
+    case AND:      
+    case OR:
+    case EQUAL:
+    case NOT_EQUAL:
+    case LTH:
+    case LEQ:
+    case GTH:
+    case GEQ:
+    case PLUS:
+    case MINUS:
+    case MULTIPLY:
+    case DIVIDE:
+    case CONST:
+    case FUNCTION:
+        return expr.getValueType();
+
+    case FIELD:
+      FieldEval fieldEval = (FieldEval) expr;
+      return inputSchema.getColumn(fieldEval.getName()).getDataType();
+
+      
+    default:
+      throw new InternalException("Unknown expr type: " 
+          + expr.getType().toString());
+    }
+  }
+
+  /**
+   * Return all exprs to refer columns corresponding to the target.
+   *
+   * @param expr
+   * @param target to be found
+   * @return a list of exprs
+   */
+  public static Collection<EvalNode> getContainExpr(EvalNode expr, Column target) {
+    Set<EvalNode> exprSet = Sets.newHashSet();
+    getContainExpr(expr, target, exprSet);
+    return exprSet;
+  }
+  
+  /**
+   * Return the counter to count the number of expression types individually.
+   *  
+   * @param expr
+   * @return
+   */
+  public static Map<EvalType, Integer> getExprCounters(EvalNode expr) {
+    VariableCounter counter = new VariableCounter();
+    expr.postOrder(counter);
+    return counter.getCounter();
+  }
+  
+  private static void getContainExpr(EvalNode expr, Column target, Set<EvalNode> exprSet) {
+    switch (expr.getType()) {
+    case EQUAL:
+    case LTH:
+    case LEQ:
+    case GTH:
+    case GEQ:
+    case NOT_EQUAL:
+      if (containColumnRef(expr, target)) {          
+        exprSet.add(expr);
+      }
+    }    
+  }
+  
+  /**
+   * Examine if the expr contains the column reference corresponding 
+   * to the target column
+   */
+  public static boolean containColumnRef(EvalNode expr, Column target) {
+    Set<EvalNode> exprSet = Sets.newHashSet();
+    _containColumnRef(expr, target, exprSet);
+    
+    return exprSet.size() > 0;
+  }
+  
+  private static void _containColumnRef(EvalNode expr, Column target, 
+      Set<EvalNode> exprSet) {
+    switch (expr.getType()) {
+    case FIELD:
+      FieldEval field = (FieldEval) expr;
+      if (field.getColumnName().equals(target.getSimpleName())) {
+        exprSet.add(field);
+      }
+      break;
+    case CONST:
+      return;
+    default: 
+      _containColumnRef(expr.getLeftExpr(), target, exprSet);
+      _containColumnRef(expr.getRightExpr(), target, exprSet);
+    }    
+  }
+
+  /**
+   * If a given expression is join condition, it returns TRUE. Otherwise, it returns FALSE.
+   *
+   * @param expr EvalNode to be evaluated
+   * @param includeThetaJoin If true, it will return equi as well as non-equi join conditions.
+   *                         Otherwise, it only returns equi-join conditions.
+   * @return True if it is join condition.
+   */
+  public static boolean isJoinQual(EvalNode expr, boolean includeThetaJoin) {
+    boolean joinComparator;
+    if (includeThetaJoin) {
+      joinComparator = AlgebraicUtil.isComparisonOperator(expr);
+    } else {
+      joinComparator = expr.getType() == EvalType.EQUAL;
+    }
+
+    return joinComparator && expr.getLeftExpr().getType() == EvalType.FIELD &&
+        expr.getRightExpr().getType() == EvalType.FIELD;
+  }
+  
+  public static class ChangeColumnRefVisitor implements EvalNodeVisitor {    
+    private final String findColumn;
+    private final String toBeChanged;
+    
+    public ChangeColumnRefVisitor(String oldName, String newName) {
+      this.findColumn = oldName;
+      this.toBeChanged = newName;
+    }
+    
+    @Override
+    public void visit(EvalNode node) {
+      if (node.type == EvalType.FIELD) {
+        FieldEval field = (FieldEval) node;
+        if (field.getColumnName().equals(findColumn)
+            || field.getName().equals(findColumn)) {
+          field.replaceColumnRef(toBeChanged);
+        }
+      }
+    }    
+  }
+  
+  public static class AllColumnRefFinder implements EvalNodeVisitor {
+    private List<Column> colList = new ArrayList<Column>();
+    private FieldEval field = null;
+    
+    @Override
+    public void visit(EvalNode node) {
+      if (node.getType() == EvalType.FIELD) {
+        field = (FieldEval) node;
+        colList.add(field.getColumnRef());
+      } 
+    }
+    
+    public List<Column> getColumnRefs() {
+      return this.colList;
+    }
+  }
+  
+  public static class UniqueColumnFinder implements EvalNodeVisitor {
+    private LinkedHashSet<Column> columnSet = Sets.newLinkedHashSet();
+    private FieldEval field = null;
+    
+    @Override
+    public void visit(EvalNode node) {
+      if (node.getType() == EvalType.FIELD) {
+        field = (FieldEval) node;
+        columnSet.add(field.getColumnRef());
+      }
+    }
+    
+    public LinkedHashSet<Column> getColumnRefs() {
+      return this.columnSet;
+    }
+  }
+  
+  public static class VariableCounter implements EvalNodeVisitor {
+    private final Map<EvalType, Integer> counter;
+    
+    public VariableCounter() {
+      counter = Maps.newHashMap();
+      counter.put(EvalType.FUNCTION, 0);
+      counter.put(EvalType.FIELD, 0);
+    }
+    
+    @Override
+    public void visit(EvalNode node) {
+      if (counter.containsKey(node.getType())) {
+        int val = counter.get(node.getType());
+        val++;
+        counter.put(node.getType(), val);
+      }
+    }
+    
+    public Map<EvalType, Integer> getCounter() {
+      return counter;
+    }
+  }
+
+  public static Set<AggregationFunctionCallEval> findDistinctAggFunction(EvalNode expr) {
+    AllAggFunctionFinder finder = new AllAggFunctionFinder();
+    expr.postOrder(finder);
+    return finder.getAggregationFunction();
+  }
+
+  public static class AllAggFunctionFinder implements EvalNodeVisitor {
+    private Set<AggregationFunctionCallEval> aggFucntions = Sets.newHashSet();
+    private AggregationFunctionCallEval field = null;
+
+    @Override
+    public void visit(EvalNode node) {
+      if (node.getType() == EvalType.AGG_FUNCTION) {
+        field = (AggregationFunctionCallEval) node;
+        aggFucntions.add(field);
+      }
+    }
+
+    public Set<AggregationFunctionCallEval> getAggregationFunction() {
+      return this.aggFucntions;
+    }
+  }
+
+  public static <T extends EvalNode> Collection<T> findEvalsByType(EvalNode evalNode, EvalType type) {
+    EvalFinder finder = new EvalFinder(type);
+    finder.visitChild(null, evalNode, new Stack<EvalNode>());
+    return (Collection<T>) finder.evalNodes;
+  }
+
+  public static class EvalFinder extends BasicEvalNodeVisitor<Object, Object> {
+    private EvalType targetType;
+    List<EvalNode> evalNodes = TUtil.newList();
+
+    public EvalFinder(EvalType targetType) {
+      this.targetType = targetType;
+    }
+
+    @Override
+    public Object visitChild(Object context, EvalNode evalNode, Stack<EvalNode> stack) {
+      super.visitChild(context, evalNode, stack);
+
+      if (evalNode.type == targetType) {
+        evalNodes.add(evalNode);
+      }
+
+      return evalNode;
+    }
+  }
+
+  public static boolean checkIfCanBeConstant(EvalNode evalNode) {
+    return findUniqueColumns(evalNode).size() == 0 && findDistinctAggFunction(evalNode).size() == 0;
+  }
+
+  public static Datum evaluateImmediately(EvalNode evalNode) {
+    return evalNode.eval(null, null);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..71db934
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/EvalType.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.eval;
+
+public enum EvalType {
+  // Unary expression
+  NOT(NotEval.class, "!"),
+
+  // Binary expression
+  AND(BinaryEval.class),
+  OR(BinaryEval.class),
+  EQUAL(BinaryEval.class, "="),
+  IS_NULL(IsNullEval.class),
+  NOT_EQUAL(BinaryEval.class, "<>"),
+  LTH(BinaryEval.class, "<"),
+  LEQ(BinaryEval.class, "<="),
+  GTH(BinaryEval.class, ">"),
+  GEQ(BinaryEval.class, ">="),
+  PLUS(BinaryEval.class, "+"),
+  MINUS(BinaryEval.class, "-"),
+  MODULAR(BinaryEval.class, "%"),
+  MULTIPLY(BinaryEval.class, "*"),
+  DIVIDE(BinaryEval.class, "/"),
+
+  // Function
+  AGG_FUNCTION(AggregationFunctionCallEval.class),
+  FUNCTION(GeneralFunctionEval.class),
+
+  // String operator or pattern matching predicates
+  LIKE(LikePredicateEval.class),
+  SIMILAR_TO(SimilarToPredicateEval.class),
+  REGEX(RegexPredicateEval.class),
+  CONCATENATE(BinaryEval.class, "||"),
+
+  // Other predicates
+  BETWEEN(BetweenPredicateEval.class),
+  CASE(CaseWhenEval.class),
+  IF_THEN(CaseWhenEval.IfThenEval.class),
+  IN(InEval.class),
+
+  // Value or Reference
+  SIGNED(SignedEval.class),
+  CAST(CastEval.class),
+  ROW_CONSTANT(RowConstantEval.class),
+  FIELD(FieldEval.class),
+  CONST(ConstEval.class);
+
+  private Class<? extends EvalNode> baseClass;
+  private String operatorName;
+
+  EvalType(Class<? extends EvalNode> type) {
+    this.baseClass = type;
+  }
+
+  EvalType(Class<? extends EvalNode> type, String text) {
+    this(type);
+    this.operatorName = text;
+  }
+
+  public String getOperatorName() {
+    return operatorName != null ? operatorName : name();
+  }
+
+  public Class<? extends EvalNode> getBaseClass() {
+    return this.baseClass;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/FieldEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
new file mode 100644
index 0000000..ea2b031
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FieldEval.java
@@ -0,0 +1,114 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.storage.Tuple;
+
+public class FieldEval extends EvalNode implements Cloneable {
+	@Expose private Column column;
+	@Expose	private int fieldId = -1;
+	
+	public FieldEval(String columnName, DataType domain) {
+		super(EvalType.FIELD);
+		this.column = new Column(columnName, domain);
+	}
+	
+	public FieldEval(Column column) {
+	  super(EvalType.FIELD);
+	  this.column = column;
+	}
+
+	@Override
+	public Datum eval(Schema schema, Tuple tuple) {
+	  if (fieldId == -1) {
+	    fieldId = schema.getColumnId(column.getQualifiedName());
+      if (fieldId == -1) {
+        throw new IllegalStateException("No Such Column Reference: " + column + ", schema: " + schema);
+      }
+	  }
+	  return tuple.get(fieldId);
+  }
+
+  @Override
+	public DataType getValueType() {
+		return column.getDataType();
+	}
+	
+  public Column getColumnRef() {
+    return column;
+  }
+	
+	public String getQualifier() {
+	  return column.getQualifier();
+	}
+	
+	public String getColumnName() {
+	  return column.getSimpleName();
+	}
+	
+	public void replaceColumnRef(String columnName) {
+	  this.column = new Column(columnName, this.column.getDataType());
+	}
+
+	@Override
+	public String getName() {
+		return this.column.getQualifiedName();
+	}
+	
+	public String toString() {
+	  return this.column.toString();
+	}
+	
+  public boolean equals(Object obj) {
+    if (obj instanceof FieldEval) {
+      FieldEval other = (FieldEval) obj;
+      
+      return column.equals(other.column);      
+    }
+    return false;
+  }
+  
+  @Override
+  public int hashCode() {
+    return column.hashCode();
+  }
+  
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    FieldEval eval = (FieldEval) super.clone();
+    eval.column = this.column;
+    eval.fieldId = fieldId;
+    
+    return eval;
+  }
+
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+  
+  @Override
+  public void postOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..de982e5
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/FunctionEval.java
@@ -0,0 +1,144 @@
+/**
+ * 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.eval;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.FunctionDesc;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.util.TUtil;
+
+import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType.DISTINCT_AGGREGATION;
+import static org.apache.tajo.catalog.proto.CatalogProtos.FunctionType.DISTINCT_UDA;
+
+public abstract class FunctionEval extends EvalNode implements Cloneable {
+  public static enum ParamType {
+    CONSTANT, VARIABLE, NULL
+  }
+
+  @Expose protected FunctionDesc funcDesc;
+	@Expose protected EvalNode [] argEvals;
+
+	public FunctionEval(EvalType type, FunctionDesc funcDesc, EvalNode[] argEvals) {
+		super(type);
+		this.funcDesc = funcDesc;
+		this.argEvals = argEvals;
+	}
+
+  public ParamType [] getParamType() {
+    ParamType [] paramTypes = new ParamType[argEvals.length];
+    for (int i = 0; i < argEvals.length; i++) {
+      if (argEvals[i].getType() == EvalType.CONST) {
+        if (argEvals[i].getValueType().getType() == TajoDataTypes.Type.NULL_TYPE) {
+          paramTypes[i] = ParamType.NULL;
+        } else {
+          paramTypes[i] = ParamType.CONSTANT;
+        }
+      } else {
+        paramTypes[i] = ParamType.VARIABLE;
+      }
+    }
+    return paramTypes;
+  }
+
+  public boolean isDistinct() {
+    return funcDesc.getFuncType() == DISTINCT_AGGREGATION || funcDesc.getFuncType() == DISTINCT_UDA;
+  }
+	
+	public EvalNode [] getArgs() {
+	  return this.argEvals;
+	}
+
+  public void setArgs(EvalNode [] args) {
+    this.argEvals = args;
+  }
+	
+	public DataType getValueType() {
+		return this.funcDesc.getReturnType();
+	}
+
+	@Override
+	public abstract Datum eval(Schema schema, Tuple tuple);
+
+	@Override
+	public String getName() {
+		return funcDesc.getSignature();
+	}
+
+  @Override
+	public String toString() {
+		StringBuilder sb = new StringBuilder();
+		for(int i=0; i < argEvals.length; i++) {
+			sb.append(argEvals[i]);
+			if(i+1 < argEvals.length)
+				sb.append(",");
+		}
+		return funcDesc.getSignature() + "(" + (isDistinct() ? " distinct" : "") + sb+")";
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+	  if (obj instanceof FunctionEval) {
+      FunctionEval other = (FunctionEval) obj;
+
+      boolean b1 = this.type == other.type;
+      boolean b2 = TUtil.checkEquals(funcDesc, other.funcDesc);
+      boolean b3 = TUtil.checkEquals(argEvals, other.argEvals);
+      return b1 && b2 && b3;
+	  }
+	  
+	  return false;
+	}
+	
+	@Override
+	public int hashCode() {
+	  return Objects.hashCode(funcDesc, argEvals);
+	}
+	
+	@Override
+  public Object clone() throws CloneNotSupportedException {
+    FunctionEval eval = (FunctionEval) super.clone();
+    eval.funcDesc = (FunctionDesc) funcDesc.clone();
+    eval.argEvals = new EvalNode[argEvals.length];
+    for (int i = 0; i < argEvals.length; i++) {
+      eval.argEvals[i] = (EvalNode) argEvals[i].clone();
+    }    
+    return eval;
+  }
+	
+	@Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    for (EvalNode eval : argEvals) {
+      eval.postOrder(visitor);
+    }
+    visitor.visit(this);
+  }
+	
+	@Override
+	public void postOrder(EvalNodeVisitor visitor) {
+	  for (EvalNode eval : argEvals) {
+	    eval.postOrder(visitor);
+	  }
+	  visitor.visit(this);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
new file mode 100644
index 0000000..9446d70
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/GeneralFunctionEval.java
@@ -0,0 +1,81 @@
+/**
+ * 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.eval;
+
+import com.google.common.base.Objects;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.FunctionDesc;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.engine.function.GeneralFunction;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.storage.VTuple;
+import org.apache.tajo.util.TUtil;
+
+public class GeneralFunctionEval extends FunctionEval {
+  @Expose protected GeneralFunction instance;
+  private Tuple params = null;
+
+	public GeneralFunctionEval(FunctionDesc desc, GeneralFunction instance, EvalNode[] givenArgs) {
+		super(EvalType.FUNCTION, desc, givenArgs);
+		this.instance = instance;
+    this.instance.init(getParamType());
+  }
+
+  /* (non-Javadoc)
+    * @see nta.query.executor.eval.Expr#evalVal(Tuple)
+    */
+	@Override
+	public Datum eval(Schema schema, Tuple tuple) {
+    if (this.params == null) {
+      params = new VTuple(argEvals.length);
+    }
+    if(argEvals != null) {
+      params.clear();
+      for(int i=0;i < argEvals.length; i++) {
+        params.put(i, argEvals[i].eval(schema, tuple));
+      }
+    }
+
+    return instance.eval(params);
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+	  if (obj instanceof GeneralFunctionEval) {
+      GeneralFunctionEval other = (GeneralFunctionEval) obj;
+      return super.equals(other) &&
+          TUtil.checkEquals(instance, other.instance);
+	  }
+	  
+	  return false;
+	}
+	
+	@Override
+	public int hashCode() {
+	  return Objects.hashCode(funcDesc, instance);
+	}
+	
+	@Override
+  public Object clone() throws CloneNotSupportedException {
+    GeneralFunctionEval eval = (GeneralFunctionEval) super.clone();
+    eval.instance = (GeneralFunction) instance.clone();
+    return eval;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/InEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/InEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/InEval.java
new file mode 100644
index 0000000..51097e6
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/InEval.java
@@ -0,0 +1,86 @@
+/**
+ * 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.eval;
+
+
+import com.google.common.collect.Sets;
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
+
+import java.util.Set;
+
+public class InEval extends BinaryEval {
+  private static final TajoDataTypes.DataType RES_TYPE = CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+
+  @Expose private boolean not;
+  Set<Datum> values;
+
+  public InEval(EvalNode lhs, RowConstantEval valueList, boolean not) {
+    super(EvalType.IN, lhs, valueList);
+    this.not = not;
+  }
+
+  public boolean isNot() {
+    return this.not;
+  }
+
+  @Override
+  public TajoDataTypes.DataType getValueType() {
+    return RES_TYPE;
+  }
+
+  @Override
+  public String getName() {
+    return "?";
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    if (values == null) {
+      values = Sets.newHashSet(((RowConstantEval)rightExpr).getValues());
+    }
+
+    Datum leftValue = leftExpr.eval(schema, tuple);
+
+    if (leftValue.isNull()) {
+      return NullDatum.get();
+    }
+
+    return DatumFactory.createBool(not ^ values.contains(leftValue));
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof InEval) {
+      InEval other = (InEval) obj;
+      return super.equals(obj) && not == other.not;
+    }
+    return false;
+  }
+
+  public String toString() {
+    return leftExpr + " IN (" + rightExpr + ")";
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidCastException.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidCastException.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidCastException.java
new file mode 100644
index 0000000..b907f06
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidCastException.java
@@ -0,0 +1,36 @@
+/**
+ * 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.eval;
+
+public class InvalidCastException extends RuntimeException {
+	private static final long serialVersionUID = -5090530469575858320L;
+
+	public InvalidCastException() {
+	}
+
+	/**
+	 * @param message
+	 */
+	public InvalidCastException(String message) {
+		super(message);
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidEvalException.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidEvalException.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidEvalException.java
new file mode 100644
index 0000000..96eda91
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/InvalidEvalException.java
@@ -0,0 +1,36 @@
+/**
+ * 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.eval;
+
+public class InvalidEvalException extends RuntimeException {
+	private static final long serialVersionUID = -2897003028483298256L;
+
+	public InvalidEvalException() {
+	}
+
+	/**
+	 * @param message
+	 */
+	public InvalidEvalException(String message) {
+		super(message);
+	}
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
new file mode 100644
index 0000000..5704aa5
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/IsNullEval.java
@@ -0,0 +1,84 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.storage.Tuple;
+
+public class IsNullEval extends BinaryEval {
+  // it's just a hack to emulate a binary expression
+  private final static ConstEval DUMMY_EVAL = new ConstEval(DatumFactory.createBool(true));
+  private static final DataType RES_TYPE = CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+
+  // persistent variables
+  @Expose private boolean isNot;
+
+  public IsNullEval(boolean not, EvalNode predicand) {
+    super(EvalType.IS_NULL, predicand, DUMMY_EVAL);
+    this.isNot = not;
+  }
+
+  @Override
+  public DataType getValueType() {
+    return RES_TYPE;
+  }
+
+  @Override
+  public String getName() {
+    return "?";
+  }
+
+  @Override
+  public String toString() {
+    return leftExpr + " IS " + (isNot ? "NOT NULL" : "NULL");
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    boolean isNull = leftExpr.eval(schema, tuple).isNull();
+    return DatumFactory.createBool(isNot ^ isNull);
+  }
+
+  public boolean isNot() {
+    return isNot;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof IsNullEval) {
+      IsNullEval other = (IsNullEval) obj;
+      return super.equals(other) && isNot == other.isNot();
+    } else {
+      return false;
+    }
+  }
+
+  public Object clone() throws CloneNotSupportedException {
+    IsNullEval isNullEval = (IsNullEval) super.clone();
+    isNullEval.isNot = isNot;
+
+    return isNullEval;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..bfac33e
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/LikePredicateEval.java
@@ -0,0 +1,50 @@
+/**
+ * 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.eval;
+
+import org.apache.tajo.util.StringUtils;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class LikePredicateEval extends PatternMatchPredicateEval {
+
+  public LikePredicateEval(boolean not, EvalNode field, ConstEval pattern, boolean caseSensitive) {
+    super(EvalType.LIKE, not, field, pattern, caseSensitive);
+  }
+
+  protected void compile(String pattern) throws PatternSyntaxException {
+    String escaped = StringUtils.escapeRegexp(pattern);
+    String regex = escaped.replace("_", ".").replace("%", ".*");
+    int flags = Pattern.DOTALL;
+    if (caseInsensitive) {
+      flags |= Pattern.CASE_INSENSITIVE;
+    }
+    this.compiled = Pattern.compile(regex, flags);
+  }
+
+  public boolean isLeadingWildCard() {
+    return pattern.indexOf(".*") == 0;
+  }
+
+  @Override
+  public String toString() {
+    return leftExpr.toString() + (caseInsensitive ? "ILIKE" : "LIKE") + "'" + pattern +"'";
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/NotEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/NotEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/NotEval.java
new file mode 100644
index 0000000..1a16af4
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/NotEval.java
@@ -0,0 +1,92 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.storage.Tuple;
+
+public class NotEval extends EvalNode implements Cloneable {
+  @Expose private EvalNode childEval;
+  private static final DataType RES_TYPE = CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+
+  public NotEval(EvalNode childEval) {
+    super(EvalType.NOT);
+    this.childEval = childEval;
+  }
+
+  public EvalNode getChild() {
+    return childEval;
+  }
+
+  @Override
+  public DataType getValueType() {
+    return RES_TYPE;
+  }
+
+  @Override
+  public String getName() {
+    return "?";
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    Datum datum = childEval.eval(schema, tuple);
+    return !datum.isNull() ? DatumFactory.createBool(!datum.asBool()) : datum;
+  }
+
+  @Override
+  public String toString() {
+    return "NOT " + childEval.toString();
+  }
+
+  @Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+    childEval.preOrder(visitor);
+  }
+
+  @Override
+  public void postOrder(EvalNodeVisitor visitor) {    
+    childEval.postOrder(visitor);
+    visitor.visit(this);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof NotEval) {
+      NotEval other = (NotEval) obj;
+      return this.childEval.equals(other.childEval);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    NotEval eval = (NotEval) super.clone();
+    eval.childEval = (EvalNode) this.childEval.clone();
+    return eval;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
new file mode 100644
index 0000000..0f4411d
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/PartialBinaryExpr.java
@@ -0,0 +1,70 @@
+/**
+ * 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.eval;
+
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.storage.Tuple;
+
+public class PartialBinaryExpr extends EvalNode {
+  
+  public PartialBinaryExpr(EvalType type) {
+    super(type);
+  }
+
+  public PartialBinaryExpr(EvalType type, EvalNode left, EvalNode right) {
+    super(type, left, right);
+  }
+
+  @Override
+  public DataType getValueType() {
+    return null;
+  }
+
+  @Override
+  public String getName() {
+    return "nonamed";
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    throw new InvalidEvalException(
+        "ERROR: the partial binary expression cannot be evluated: "
+            + this.toString() );
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof PartialBinaryExpr) {
+      PartialBinaryExpr other = (PartialBinaryExpr) obj;
+      return type.equals(other.type) &&
+          leftExpr.equals(other.leftExpr) &&
+          rightExpr.equals(other.rightExpr);
+    }
+    return false;
+  }
+
+  public String toString() {
+    return 
+        (leftExpr != null ? leftExpr.toString() : "[EMPTY]") 
+        + " " + type + " " 
+        + (rightExpr != null ? rightExpr.toString() : "[EMPTY]");
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/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
new file mode 100644
index 0000000..8d78b0b
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/PatternMatchPredicateEval.java
@@ -0,0 +1,82 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public abstract class PatternMatchPredicateEval extends BinaryEval {
+  private static final DataType RES_TYPE = CatalogUtil.newSimpleDataType(TajoDataTypes.Type.BOOLEAN);
+
+  @Expose protected boolean not;
+  @Expose protected String pattern;
+  @Expose protected boolean caseInsensitive;
+
+  // transient variables
+  protected Pattern compiled;
+
+  public PatternMatchPredicateEval(EvalType evalType, boolean not, EvalNode predicand, ConstEval pattern,
+                                   boolean caseInsensitive) {
+    super(evalType, predicand, pattern);
+    this.not = not;
+    this.pattern = pattern.getValue().asChars();
+    this.caseInsensitive = caseInsensitive;
+  }
+
+  public PatternMatchPredicateEval(EvalType evalType, boolean not, EvalNode field, ConstEval pattern) {
+    this(evalType, not, field, pattern, false);
+  }
+
+  abstract void compile(String pattern) throws PatternSyntaxException;
+
+  @Override
+  public DataType getValueType() {
+    return RES_TYPE;
+  }
+
+  @Override
+  public String getName() {
+    return "?";
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    if (this.compiled == null) {
+      compile(this.pattern);
+    }
+
+    Datum predicand = leftExpr.eval(schema, tuple);
+    if (predicand.isNull()) {
+      return NullDatum.get();
+    }
+
+    boolean matched = compiled.matcher(predicand.asChars()).matches();
+    return DatumFactory.createBool(matched ^ not);
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/RegexPredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/RegexPredicateEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/RegexPredicateEval.java
new file mode 100644
index 0000000..f1e0241
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/RegexPredicateEval.java
@@ -0,0 +1,53 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class RegexPredicateEval extends PatternMatchPredicateEval {
+  @Expose private String operator;
+  public RegexPredicateEval(boolean not, EvalNode field, ConstEval pattern, boolean caseInsensitive) {
+    super(EvalType.REGEX, not, field, pattern, caseInsensitive);
+    StringBuilder sb = new StringBuilder();
+    if (not) {
+      sb.append("!");
+    }
+    sb.append("~");
+    if (caseInsensitive) {
+      sb.append("*");
+    }
+    this.operator = sb.toString();
+  }
+  
+  protected void compile(String regex) throws PatternSyntaxException {
+    int flags = Pattern.DOTALL;
+    if (caseInsensitive) {
+      flags |= Pattern.CASE_INSENSITIVE;
+    }
+    this.compiled = Pattern.compile(regex, flags);
+  }
+
+  @Override
+  public String toString() {
+    return leftExpr.toString() + operator + "'" + pattern +"'";
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java
new file mode 100644
index 0000000..646a627
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/RowConstantEval.java
@@ -0,0 +1,79 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.CatalogUtil;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.storage.Tuple;
+import org.apache.tajo.util.TUtil;
+
+import static org.apache.tajo.common.TajoDataTypes.DataType;
+
+public class RowConstantEval extends EvalNode {
+  @Expose Datum [] values;
+
+  public RowConstantEval(Datum [] values) {
+    super(EvalType.ROW_CONSTANT);
+    this.values = values;
+  }
+
+  @Override
+  public DataType getValueType() {
+    return CatalogUtil.newSimpleDataType(values[0].type());
+  }
+
+  @Override
+  public String getName() {
+    return "ROW";
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    return NullDatum.get();
+  }
+
+  public Datum [] getValues() {
+    return values;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof RowConstantEval) {
+      RowConstantEval other = (RowConstantEval) obj;
+      return TUtil.checkEquals(values, other.values);
+    }
+
+    return false;
+  }
+
+  public String toString() {
+    return TUtil.arrayToString(values);
+  }
+
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+
+  public void postOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/SignedEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
new file mode 100644
index 0000000..3c2eeb4
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/SignedEval.java
@@ -0,0 +1,99 @@
+/**
+ * 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.eval;
+
+import com.google.gson.annotations.Expose;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.DataType;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.NumericDatum;
+import org.apache.tajo.storage.Tuple;
+
+public class SignedEval extends EvalNode implements Cloneable {
+  @Expose private EvalNode childEval;
+  @Expose private boolean negative;
+
+  public SignedEval(boolean negative, EvalNode childEval) {
+    super(EvalType.SIGNED);
+    this.negative = negative;
+    this.childEval = childEval;
+  }
+
+  public boolean isNegative() {
+    return negative;
+  }
+
+  public EvalNode getChild() {
+    return childEval;
+  }
+
+  @Override
+  public DataType getValueType() {
+    return childEval.getValueType();
+  }
+
+  @Override
+  public String getName() {
+    return "?";
+  }
+
+  @Override
+  public Datum eval(Schema schema, Tuple tuple) {
+    NumericDatum result = childEval.eval(schema, tuple);
+    if (negative) {
+      return result.inverseSign();
+    }
+    return result;
+  }
+
+  @Override
+  public String toString() {
+    return (negative ? "-" : "+") + childEval.toString();
+  }
+
+  @Override
+  public void preOrder(EvalNodeVisitor visitor) {
+    visitor.visit(this);
+    childEval.preOrder(visitor);
+  }
+
+  @Override
+  public void postOrder(EvalNodeVisitor visitor) {    
+    childEval.postOrder(visitor);
+    visitor.visit(this);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof SignedEval) {
+      SignedEval other = (SignedEval) obj;
+      return negative == other.negative && this.childEval.equals(other.childEval);
+    } else {
+      return false;
+    }
+  }
+
+  @Override
+  public Object clone() throws CloneNotSupportedException {
+    SignedEval eval = (SignedEval) super.clone();
+    eval.negative = negative;
+    eval.childEval = (EvalNode) this.childEval.clone();
+    return eval;
+  }
+}

http://git-wip-us.apache.org/repos/asf/tajo/blob/6594ac1c/tajo-core/src/main/java/org/apache/tajo/engine/eval/SimilarToPredicateEval.java
----------------------------------------------------------------------
diff --git a/tajo-core/src/main/java/org/apache/tajo/engine/eval/SimilarToPredicateEval.java b/tajo-core/src/main/java/org/apache/tajo/engine/eval/SimilarToPredicateEval.java
new file mode 100644
index 0000000..9ac0e62
--- /dev/null
+++ b/tajo-core/src/main/java/org/apache/tajo/engine/eval/SimilarToPredicateEval.java
@@ -0,0 +1,43 @@
+/**
+ * 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.eval;
+
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+public class SimilarToPredicateEval extends PatternMatchPredicateEval {
+  private static final String SIMILARTO_ESCAPE_SPATIAL_CHARACTERS = "([.])";
+
+  public SimilarToPredicateEval(boolean not, EvalNode field, ConstEval pattern) {
+    super(EvalType.SIMILAR_TO, not, field, pattern);
+  }
+
+  @Override
+  protected void compile(String pattern) throws PatternSyntaxException {
+    String regex = pattern.replaceAll(SIMILARTO_ESCAPE_SPATIAL_CHARACTERS, "\\\\$1");
+    regex = regex.replace("_", ".").replace("%", ".*"); // transform some special characters to be 'like'.
+
+    this.compiled = Pattern.compile(regex, Pattern.DOTALL);
+  }
+  
+  @Override
+  public String toString() {
+    return leftExpr.toString() + " SIMILAR TO '" + pattern + "'";
+  }
+}
\ No newline at end of file


Mime
View raw message