tajo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jh...@apache.org
Subject git commit: TAJO-119: Refactor and Improve Datum. (jinho)
Date Sat, 14 Sep 2013 11:56:17 GMT
Updated Branches:
  refs/heads/master 3915d85e9 -> 53df7f455


TAJO-119: Refactor and Improve Datum. (jinho)


Project: http://git-wip-us.apache.org/repos/asf/incubator-tajo/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tajo/commit/53df7f45
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tajo/tree/53df7f45
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tajo/diff/53df7f45

Branch: refs/heads/master
Commit: 53df7f45594b29ee12d3242720db769419f4d771
Parents: 3915d85
Author: jinossy <jinossy@gmail.com>
Authored: Sat Sep 14 20:55:11 2013 +0900
Committer: jinossy <jinossy@gmail.com>
Committed: Sat Sep 14 20:55:11 2013 +0900

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +
 .../java/org/apache/tajo/datum/BitDatum.java    |   6 +
 .../main/java/org/apache/tajo/datum/Datum.java  |   6 +-
 .../java/org/apache/tajo/datum/Float4Datum.java |   8 +-
 .../java/org/apache/tajo/datum/Float8Datum.java |   8 +-
 .../java/org/apache/tajo/datum/Int2Datum.java   |   8 +-
 .../java/org/apache/tajo/datum/Int4Datum.java   |   8 +-
 .../java/org/apache/tajo/datum/Int8Datum.java   |  10 +-
 .../java/org/apache/tajo/datum/NullDatum.java   |  19 +-
 .../org/apache/tajo/datum/NumericDatum.java     |  18 +-
 .../java/org/apache/tajo/datum/TextDatum.java   |   5 +
 .../main/java/org/apache/tajo/util/Bytes.java   | 113 ++++++-
 .../java/org/apache/tajo/util/NumberUtil.java   |  43 +++
 .../org/apache/tajo/datum/TestBitDatum.java     |   8 +
 .../org/apache/tajo/datum/TestBoolDatum.java    |   7 +
 .../org/apache/tajo/datum/TestBytesDatum.java   |   7 +
 .../org/apache/tajo/datum/TestCharDatum.java    |   9 +-
 .../org/apache/tajo/datum/TestFloat8Datum.java  |   7 +
 .../org/apache/tajo/datum/TestFloatDatum.java   |   7 +
 .../org/apache/tajo/datum/TestInet4Datum.java   |   7 +
 .../org/apache/tajo/datum/TestInt2Datum.java    |   7 +
 .../org/apache/tajo/datum/TestInt4Datum.java    |   7 +
 .../org/apache/tajo/datum/TestInt8Datum.java    |   7 +
 .../org/apache/tajo/datum/TestTextDatum.java    |   7 +
 .../java/org/apache/tajo/util/TestBytes.java    |  64 ++++
 .../org/apache/tajo/util/TestNumberUtil.java    |  48 +++
 .../tajo/engine/query/TestNullValues.java       |  11 +-
 .../tajo/engine/query/TestSelectQuery.java      |  18 +-
 .../java/org/apache/tajo/storage/CSVFile.java   | 271 +++++++---------
 .../java/org/apache/tajo/storage/LazyTuple.java | 309 +++++++++++++++++++
 .../java/org/apache/tajo/storage/VTuple.java    |  21 +-
 .../org/apache/tajo/storage/TestLazyTuple.java  | 212 +++++++++++++
 32 files changed, 1088 insertions(+), 200 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index e22f6f7..73c3b61 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -25,6 +25,8 @@ Release 0.2.0 - unreleased
 
   IMPROVEMENTS
 
+    TAJO-119: Refactor and Improve Datum. (jinho)
+
     TAJO-178: Implements StorageManager for scanning asynchronously. 
     (hyoungjunkim via hyunsik)
 

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
index f5c60f6..17f9382 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/BitDatum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.util.NumberUtil;
 
 public class BitDatum extends Datum {
   private static final int size = 1;
@@ -82,6 +83,11 @@ public class BitDatum extends Datum {
 	}
 
   @Override
+  public byte[] asTextBytes() {
+    return NumberUtil.toAsciiBytes(asInt4());
+  }
+
+  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
index 10ae9d9..1ae72c7 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Datum.java
@@ -19,10 +19,10 @@
 package org.apache.tajo.datum;
 
 import com.google.gson.annotations.Expose;
-import org.apache.tajo.json.GsonObject;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
 import org.apache.tajo.json.CommonGsonHelper;
+import org.apache.tajo.json.GsonObject;
 
 import static org.apache.tajo.common.TajoDataTypes.Type;
 
@@ -83,6 +83,10 @@ public abstract class Datum implements Comparable<Datum>, GsonObject {
 	public String asChars() {
     throw new InvalidCastException(type + " cannot be casted to STRING type");
   }
+
+  public byte[] asTextBytes() {
+    return toString().getBytes();
+  }
 	
 	public boolean isNumeric() {
 	  return isNumber() || isReal();

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
index 3bdd332..84245b2 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float4Datum.java
@@ -22,10 +22,11 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.util.NumberUtil;
 
 import java.nio.ByteBuffer;
 
-public class Float4Datum extends NumericDatum {
+public class Float4Datum extends Datum implements NumericDatum {
   private static final int size = 4;
   @Expose float val;
 
@@ -91,6 +92,11 @@ public class Float4Datum extends NumericDatum {
 	}
 
   @Override
+  public byte[] asTextBytes() {
+    return NumberUtil.toAsciiBytes(val);
+  }
+
+  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
index a27b4fc..d9389f4 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Float8Datum.java
@@ -24,10 +24,11 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.util.NumberUtil;
 
 import java.nio.ByteBuffer;
 
-public class Float8Datum extends NumericDatum {
+public class Float8Datum extends Datum implements NumericDatum {
   private static final int size = 8;
   @Expose private double val;
 
@@ -84,6 +85,11 @@ public class Float8Datum extends NumericDatum {
 	}
 
   @Override
+  public byte[] asTextBytes() {
+    return NumberUtil.toAsciiBytes(val);
+  }
+
+  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
index 7523432..4101e12 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int2Datum.java
@@ -21,10 +21,11 @@ package org.apache.tajo.datum;
 import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.util.NumberUtil;
 
 import java.nio.ByteBuffer;
 
-public class Int2Datum extends NumericDatum {
+public class Int2Datum extends Datum implements NumericDatum {
   private static final int size = 2;  
   @Expose private short val;
 
@@ -81,6 +82,11 @@ public class Int2Datum extends NumericDatum {
 	}
 
   @Override
+  public byte[] asTextBytes() {
+    return NumberUtil.toAsciiBytes(val);
+  }
+
+  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
index 0c993a3..0b95229 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int4Datum.java
@@ -22,10 +22,11 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.util.NumberUtil;
 
 import java.nio.ByteBuffer;
 
-public class Int4Datum extends NumericDatum {
+public class Int4Datum extends Datum implements NumericDatum {
   private static final int size = 4;
   @Expose private int val;
 	
@@ -87,6 +88,11 @@ public class Int4Datum extends NumericDatum {
 	}
 
   @Override
+  public byte[] asTextBytes() {
+    return NumberUtil.toAsciiBytes(val);
+  }
+
+  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
index f93c219..dd00cb4 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/Int8Datum.java
@@ -22,10 +22,11 @@ import com.google.gson.annotations.Expose;
 import org.apache.tajo.common.TajoDataTypes;
 import org.apache.tajo.datum.exception.InvalidCastException;
 import org.apache.tajo.datum.exception.InvalidOperationException;
+import org.apache.tajo.util.NumberUtil;
 
 import java.nio.ByteBuffer;
 
-public class Int8Datum extends NumericDatum {
+public class Int8Datum extends Datum implements NumericDatum {
   private static final int size = 8;
   @Expose private long val;
 
@@ -90,7 +91,12 @@ public class Int8Datum extends NumericDatum {
 	public String asChars() {
 		return ""+val;
 	}
-	
+
+  @Override
+  public byte[] asTextBytes() {
+    return NumberUtil.toAsciiBytes(val);
+  }
+
   @Override
   public int size() {
     return size;

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
index 51d74e9..500f402 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/NullDatum.java
@@ -24,6 +24,8 @@ import static org.apache.tajo.common.TajoDataTypes.Type;
 
 public class NullDatum extends Datum {
   private static final NullDatum instance;
+  private static String NULL_STRING = "null";
+  private static byte[] NULL_CHAR = NULL_STRING.getBytes();
   
   static {
     instance = new NullDatum();
@@ -64,7 +66,7 @@ public class NullDatum extends Datum {
 
   @Override
   public byte[] asByteArray() {
-    return Bytes.toBytes("null");
+    return NULL_CHAR.clone();
   }
 
   @Override
@@ -79,7 +81,12 @@ public class NullDatum extends Datum {
 
   @Override
   public String asChars() {
-    return "null";
+    return NULL_STRING;
+  }
+
+  @Override
+  public byte[] asTextBytes() {
+    return asByteArray();
   }
 
   @Override
@@ -101,4 +108,12 @@ public class NullDatum extends Datum {
   public int hashCode() {
     return 23244; // one of the prime number
   }
+
+  public static boolean isNull(String val){
+    return val == null || val.length() == 0 || ((val.length() == NULL_CHAR.length) && NULL_STRING.equals(val));
+  }
+
+  public static boolean isNull(byte[] val){
+    return val == null || val.length == 0 || ((val.length == NULL_CHAR.length) && Bytes.equals(val, NULL_CHAR));
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java
index e4422c2..745b720 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/NumericDatum.java
@@ -19,21 +19,15 @@
 package org.apache.tajo.datum;
 
 
-import org.apache.tajo.common.TajoDataTypes;
+public interface NumericDatum {
 
-public abstract class NumericDatum extends Datum {
-
-  public NumericDatum(TajoDataTypes.Type type) {
-    super(type);
-  }
-  
-  public abstract Datum plus(Datum datum);
+  Datum plus(Datum datum);
   
-  public abstract Datum minus(Datum datum);
+  Datum minus(Datum datum);
   
-  public abstract Datum multiply(Datum datum);
+  Datum multiply(Datum datum);
   
-  public abstract Datum divide(Datum datum);
+  Datum divide(Datum datum);
   
-  public abstract void inverseSign();
+  void inverseSign();
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java b/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
index 876803b..bab99a2 100644
--- a/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
+++ b/tajo-common/src/main/java/org/apache/tajo/datum/TextDatum.java
@@ -89,6 +89,11 @@ public class TextDatum extends Datum {
   }
 
   @Override
+  public byte[] asTextBytes() {
+    return asByteArray();
+  }
+
+  @Override
   public int size() {
     return size;
   }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/util/Bytes.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/Bytes.java b/tajo-common/src/main/java/org/apache/tajo/util/Bytes.java
index 33dd9d9..7d5bbd3 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/Bytes.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/Bytes.java
@@ -37,8 +37,10 @@ import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.ArrayList;
 import java.util.Comparator;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * Utility class that handles byte arrays, conversions to/from other types,
@@ -425,6 +427,20 @@ public class Bytes {
   }
 
   /**
+   * Converts a char array to a ascii byte array.
+   *
+   * @param chars string
+   * @return the byte array
+   */
+  public static byte[] toASCIIBytes(char[] chars) {
+    byte[] buffer = new byte[chars.length];
+    for (int i = 0; i < chars.length; i++) {
+      buffer[i] = (byte) chars[i];
+    }
+    return buffer;
+  }
+
+  /**
    * Convert a boolean to a byte array. True becomes -1
    * and false becomes 0.
    *
@@ -1226,7 +1242,6 @@ public class Bytes {
    * @param b bytes to hash
    * @return Runs {@link org.apache.hadoop.io.WritableComparator#hashBytes(byte[], int)} on the
    * passed in array.  This method is what {@link org.apache.hadoop.io.Text} and
-   * {@link ImmutableBytesWritable} use calculating hash code.
    */
   public static int hashCode(final byte [] b) {
     return hashCode(b, b.length);
@@ -1237,7 +1252,6 @@ public class Bytes {
    * @param length length of the value
    * @return Runs {@link org.apache.hadoop.io.WritableComparator#hashBytes(byte[], int)} on the
    * passed in array.  This method is what {@link org.apache.hadoop.io.Text} and
-   * {@link ImmutableBytesWritable} use calculating hash code.
    */
   public static int hashCode(final byte [] b, final int length) {
     return WritableComparator.hashBytes(b, length);
@@ -1358,7 +1372,100 @@ public class Bytes {
     }
     return ret;
   }
-  
+
+  public static byte[][] splitPreserveAllTokens(byte[] str, char separatorChar, int[] target) {
+    return splitWorker(str, 0, separatorChar, true, target);
+  }
+
+  public static byte[][] splitPreserveAllTokens(byte[] str, int length, char separatorChar, int[] target) {
+    return splitWorker(str, length, separatorChar, true, target);
+  }
+
+  public static byte[][] splitPreserveAllTokens(byte[] str, char separatorChar) {
+    return splitWorker(str, 0, separatorChar, true, null);
+  }
+
+  public static byte[][] splitPreserveAllTokens(byte[] str, int length, char separatorChar) {
+    return splitWorker(str, length, separatorChar, true, null);
+  }
+
+  /**
+   * Performs the logic for the <code>split</code> and
+   * <code>splitPreserveAllTokens</code> methods that do not return a
+   * maximum array length.
+   *
+   * @param str  the String to parse, may be <code>null</code>
+   * @param length amount of bytes to str
+   * @param separatorChar the separate character
+   * @param preserveAllTokens if <code>true</code>, adjacent separators are
+   * @param target the projection target
+   * treated as empty token separators; if <code>false</code>, adjacent
+   * separators are treated as one separator.
+   * @return an array of parsed Strings, <code>null</code> if null String input
+   */
+  private static byte[][] splitWorker(byte[] str, int length, char separatorChar, boolean preserveAllTokens, int[] target) {
+    // Performance tuned for 2.0 (JDK1.4)
+
+    if (str == null) {
+      return null;
+    }
+    int len = length;
+    if(len < 1){
+      len = str.length;
+    }
+
+    if (len == 0) {
+      return new byte[0][];
+    }
+    List list = new ArrayList();
+    int i = 0, start = 0;
+    boolean match = false;
+    boolean lastMatch = false;
+    int currentTarget = 0;
+    int currentIndex = 0;
+    while (i < len) {
+      if (str[i] == separatorChar) {
+        if (match || preserveAllTokens) {
+          if (target == null) {
+            byte[] bytes = new byte[i - start];
+            System.arraycopy(str, start, bytes, 0, bytes.length);
+            list.add(bytes);
+          } else if (target.length > currentTarget && currentIndex == target[currentTarget]) {
+            byte[] bytes = new byte[i - start];
+            System.arraycopy(str, start, bytes, 0, bytes.length);
+            list.add(bytes);
+            currentTarget++;
+          } else {
+            list.add(null);
+          }
+          currentIndex++;
+          match = false;
+          lastMatch = true;
+        }
+        start = ++i;
+        continue;
+      }
+      lastMatch = false;
+      match = true;
+      i++;
+    }
+    if (match || (preserveAllTokens && lastMatch)) {
+      if (target == null) {
+        byte[] bytes = new byte[i - start];
+        System.arraycopy(str, start, bytes, 0, bytes.length);
+        list.add(bytes);
+      } else if (target.length > currentTarget && currentIndex == target[currentTarget]) {
+        byte[] bytes = new byte[i - start];
+        System.arraycopy(str, start, bytes, 0, bytes.length);
+        list.add(bytes); //str.substring(start, i));
+        currentTarget++;
+      } else {
+        list.add(null);
+      }
+      currentIndex++;
+    }
+    return (byte[][]) list.toArray(new byte[list.size()][]);
+  }
   /**
    * Iterate over keys within the passed inclusive range.
    */

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/main/java/org/apache/tajo/util/NumberUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/main/java/org/apache/tajo/util/NumberUtil.java b/tajo-common/src/main/java/org/apache/tajo/util/NumberUtil.java
index 25d5246..1846d78 100644
--- a/tajo-common/src/main/java/org/apache/tajo/util/NumberUtil.java
+++ b/tajo-common/src/main/java/org/apache/tajo/util/NumberUtil.java
@@ -27,4 +27,47 @@ public class NumberUtil {
 	public static int unsigned16(short n) {
 		return n & 0xFFFF;
 	}
+
+  public static byte[] toAsciiBytes(Number i){
+    return Bytes.toASCIIBytes(String.valueOf(i).toCharArray());
+  }
+
+  public static byte[] toAsciiBytes(short i){
+    return Bytes.toASCIIBytes(String.valueOf(i).toCharArray());
+  }
+
+  public static byte[] toAsciiBytes(int i){
+    return Bytes.toASCIIBytes(String.valueOf(i).toCharArray());
+  }
+
+  public static byte[] toAsciiBytes(long i){
+    return Bytes.toASCIIBytes(String.valueOf(i).toCharArray());
+  }
+
+  public static byte[] toAsciiBytes(float i){
+    return Bytes.toASCIIBytes(String.valueOf(i).toCharArray());
+  }
+
+  public static byte[] toAsciiBytes(double i){
+    return Bytes.toASCIIBytes(String.valueOf(i).toCharArray());
+  }
+
+  private static void benchmark(int num){
+    System.out.println("Start benchmark. # of :" + num);
+    long start =  System.currentTimeMillis();
+    for (int i = 0; i < num; i ++){
+      String.valueOf(i).getBytes();
+    }
+
+    long end =  System.currentTimeMillis();
+    System.out.println("JDK getBytes() \t\t\t\t" + (end - start) + " ms");
+    for (int i = 0; i < num; i ++){
+      toAsciiBytes(i);
+    }
+    System.out.println( "NumberUtil toByte() \t" + (System.currentTimeMillis() - end) + " ms");
+  }
+
+  public static void main(String[] args) throws Exception {
+    benchmark(1024 * 1024 * 10);
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestBitDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestBitDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestBitDatum.java
index ba938b2..b6b84d9 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestBitDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestBitDatum.java
@@ -19,8 +19,10 @@
 package org.apache.tajo.datum;
 
 import org.apache.tajo.common.TajoDataTypes.Type;
+import org.apache.tajo.util.NumberUtil;
 import org.junit.Test;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -73,4 +75,10 @@ public class TestBitDatum {
     Datum d = DatumFactory.createBit((byte) 1);
     assertEquals(1, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createBit((byte) 5);
+    assertArrayEquals(NumberUtil.toAsciiBytes(d.asInt4()), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
index 3ae8522..3623f88 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestBoolDatum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.apache.tajo.common.TajoDataTypes.Type;
 import org.junit.Test;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 
 public class TestBoolDatum {
@@ -72,4 +73,10 @@ public class TestBoolDatum {
     Datum d = DatumFactory.createBool(true);
     assertEquals(1, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createBool(true);
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
index 94aafe8..af2d814 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestBytesDatum.java
@@ -22,6 +22,7 @@ import org.apache.tajo.common.TajoDataTypes.Type;
 import org.apache.tajo.json.CommonGsonHelper;
 import org.junit.Test;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -52,4 +53,10 @@ public class TestBytesDatum {
 	  Datum fromJson = CommonGsonHelper.fromJson(json, Datum.class);
 	  assertTrue(d.equalsTo(fromJson).asBool());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createBlob("12345".getBytes());
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestCharDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestCharDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestCharDatum.java
index 1d6da28..bb22d5c 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestCharDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestCharDatum.java
@@ -20,9 +20,8 @@ package org.apache.tajo.datum;
 
 import org.junit.Test;
 
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
 import static org.apache.tajo.common.TajoDataTypes.Type;
+import static org.junit.Assert.*;
 
 public class TestCharDatum {
 
@@ -86,4 +85,10 @@ public class TestCharDatum {
     assertTrue(b.compareTo(a) > 0);
     assertTrue(c.compareTo(c) == 0);
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createChar("1234567890");
+    assertArrayEquals(d.asByteArray(), d.asTextBytes());
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestFloat8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestFloat8Datum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestFloat8Datum.java
index 1aed558..b2b49f2 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestFloat8Datum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestFloat8Datum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,4 +68,10 @@ public class TestFloat8Datum {
 	  Datum d = DatumFactory.createFloat8(5d);
 	  assertEquals(8, d.size());
 	}
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createFloat8(5d);
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestFloatDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestFloatDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestFloatDatum.java
index 185ba55..cd92dda 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestFloatDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestFloatDatum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,4 +68,10 @@ public class TestFloatDatum {
     Datum d = DatumFactory.createFloat4(5f);
     assertEquals(4, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createFloat4(5f);
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
index 2708386..cac900c 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestInet4Datum.java
@@ -24,6 +24,7 @@ import org.junit.Test;
 
 import java.util.Arrays;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -72,4 +73,10 @@ public class TestInet4Datum {
 		Datum fromJson = CommonGsonHelper.fromJson(json, Datum.class);
 		assertTrue(d.equalsTo(fromJson).asBool());
 	}
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createInet4("163.152.23.222");
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestInt2Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestInt2Datum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestInt2Datum.java
index 8a04a91..832f563 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestInt2Datum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestInt2Datum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,4 +68,10 @@ public class TestInt2Datum {
     Datum d = DatumFactory.createInt2((short) 5);
     assertEquals(2, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createInt2((short) 5);
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestInt4Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestInt4Datum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestInt4Datum.java
index 223fdd9..559bed3 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestInt4Datum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestInt4Datum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,4 +68,10 @@ public class TestInt4Datum {
     Datum d = DatumFactory.createInt4(5);
     assertEquals(4, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createInt4(5);
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestInt8Datum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestInt8Datum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestInt8Datum.java
index a8e6acf..7c07114 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestInt8Datum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestInt8Datum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,4 +68,10 @@ public class TestInt8Datum {
     Datum d = DatumFactory.createInt8(5l);
     assertEquals(8, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createInt8(5l);
+    assertArrayEquals(d.toString().getBytes(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/datum/TestTextDatum.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/datum/TestTextDatum.java b/tajo-common/src/test/java/org/apache/tajo/datum/TestTextDatum.java
index 07ce3ad..7feab46 100644
--- a/tajo-common/src/test/java/org/apache/tajo/datum/TestTextDatum.java
+++ b/tajo-common/src/test/java/org/apache/tajo/datum/TestTextDatum.java
@@ -21,6 +21,7 @@ package org.apache.tajo.datum;
 import org.junit.Test;
 import org.apache.tajo.common.TajoDataTypes.Type;
 
+import static org.junit.Assert.assertArrayEquals;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -67,4 +68,10 @@ public class TestTextDatum {
 	  Datum d = DatumFactory.createText("12345");
     assertEquals(5, d.size());
   }
+
+  @Test
+  public final void testAsTextBytes() {
+    Datum d = DatumFactory.createText("12345");
+    assertArrayEquals(d.asByteArray(), d.asTextBytes());
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/util/TestBytes.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/util/TestBytes.java b/tajo-common/src/test/java/org/apache/tajo/util/TestBytes.java
new file mode 100644
index 0000000..98d8eac
--- /dev/null
+++ b/tajo-common/src/test/java/org/apache/tajo/util/TestBytes.java
@@ -0,0 +1,64 @@
+/**
+ * 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.util;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestBytes {
+
+  @Test
+  public void testAsciiBytes() {
+    String asciiText = "abcde 12345 ABCDE";
+    assertArrayEquals(asciiText.getBytes(), Bytes.toASCIIBytes(asciiText.toCharArray()));
+  }
+
+  @Test
+  public void testSplitBytes() {
+    String text = "abcde|12345|ABCDE";
+    char separatorChar = '|';
+
+    String[] textArray = StringUtils.splitPreserveAllTokens(text, separatorChar);
+    byte[][] bytesArray =  Bytes.splitPreserveAllTokens(text.getBytes(), separatorChar);
+
+    assertEquals(textArray.length, bytesArray.length);
+    for (int i = 0; i < textArray.length; i++){
+      assertArrayEquals(textArray[i].getBytes(), bytesArray[i]);
+    }
+  }
+
+  @Test
+  public void testSplitProjectionBytes() {
+    String text = "abcde|12345|ABCDE";
+    int[] target = new int[]{ 1 };
+    char separatorChar = '|';
+
+    String[] textArray = StringUtils.splitPreserveAllTokens(text, separatorChar);
+    byte[][] bytesArray =  Bytes.splitPreserveAllTokens(text.getBytes(), separatorChar, target);
+
+    assertEquals(textArray.length, bytesArray.length);
+
+    assertNull(bytesArray[0]);
+    assertNotNull(bytesArray[1]);
+    assertArrayEquals(textArray[1].getBytes(), bytesArray[1]);
+    assertNull(bytesArray[2]);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-common/src/test/java/org/apache/tajo/util/TestNumberUtil.java
----------------------------------------------------------------------
diff --git a/tajo-common/src/test/java/org/apache/tajo/util/TestNumberUtil.java b/tajo-common/src/test/java/org/apache/tajo/util/TestNumberUtil.java
new file mode 100644
index 0000000..25851cd
--- /dev/null
+++ b/tajo-common/src/test/java/org/apache/tajo/util/TestNumberUtil.java
@@ -0,0 +1,48 @@
+/**
+ * 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.util;
+
+import org.junit.Test;
+
+import java.util.Random;
+
+import static org.junit.Assert.assertArrayEquals;
+
+public class TestNumberUtil {
+
+  @Test
+  public void testNumberToAsciiBytes() {
+    Random r = new Random(System.currentTimeMillis());
+
+    Number n = r.nextInt();
+    assertArrayEquals(String.valueOf(n.shortValue()).getBytes(), NumberUtil.toAsciiBytes(n.shortValue()));
+
+    n = r.nextInt();
+    assertArrayEquals(String.valueOf(n.intValue()).getBytes(), NumberUtil.toAsciiBytes(n.intValue()));
+
+    n = r.nextLong();
+    assertArrayEquals(String.valueOf(n.longValue()).getBytes(), NumberUtil.toAsciiBytes(n.longValue()));
+
+    n = r.nextFloat();
+    assertArrayEquals(String.valueOf(n.floatValue()).getBytes(), NumberUtil.toAsciiBytes(n.floatValue()));
+
+    n = r.nextDouble();
+    assertArrayEquals(String.valueOf(n.doubleValue()).getBytes(), NumberUtil.toAsciiBytes(n.doubleValue()));
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNullValues.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNullValues.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNullValues.java
index 2d478dd..3b46a9b 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNullValues.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestNullValues.java
@@ -44,17 +44,18 @@ public class TestNullValues {
     Schema schema = new Schema();
     schema.addColumn("col1", Type.INT4);
     schema.addColumn("col2", Type.TEXT);
+    schema.addColumn("col3", Type.FLOAT4);
     Schema [] schemas = new Schema[] {schema};
     String [] data = {
-        "1|filled|",
+        "1|filled|0.1",
         "2||",
-        "3|filled|"
+        "3|filled|0.2"
     };
     Options opts = new Options();
     opts.put(CSVFile.DELIMITER, "|");
     ResultSet res = TajoTestingCluster
         .run(table, schemas, opts, new String[][]{data},
-            "select * from nulltable1 where col2 is null");
+            "select * from nulltable1 where col3 is null");
     try {
       assertTrue(res.next());
       assertEquals(2, res.getInt(1));
@@ -73,14 +74,14 @@ public class TestNullValues {
     Schema [] schemas = new Schema[] {schema};
     String [] data = {
         "1|filled|",
-        "2||",
+        "||",
         "3|filled|"
     };
     Options opts = new Options();
     opts.put(CSVFile.DELIMITER, "|");
     ResultSet res = TajoTestingCluster
         .run(table, schemas, opts, new String[][]{data},
-            "select * from nulltable2 where col2 is not null");
+            "select * from nulltable2 where col1 is not null");
     try {
       assertTrue(res.next());
       assertEquals(1, res.getInt(1));

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
index f2a2a71..6c10888 100644
--- a/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
+++ b/tajo-core/tajo-core-backend/src/test/java/org/apache/tajo/engine/query/TestSelectQuery.java
@@ -147,7 +147,7 @@ public class TestSelectQuery {
       assertEquals("1996-04-20",res.getString(13));
       assertEquals("TAKE BACK RETURN",res.getString(14));
       assertEquals("MAIL",res.getString(15));
-      assertEquals("ly final dependencies: slyly bold",res.getString(16));
+      assertEquals("ly final dependencies: slyly bold ",res.getString(16));
     } finally {
       res.close();
     }
@@ -272,19 +272,19 @@ public class TestSelectQuery {
   @Test
   public final void testCaseWhenWithoutElse() throws Exception {
     ResultSet res = tpch.execute("select r_regionkey, " +
-        "case when r_regionkey = 1 then 'one' " +
-        "when r_regionkey = 2 then 'two' " +
-        "when r_regionkey = 3 then 'three' " +
-        "when r_regionkey = 4 then 'four' " +
+        "case when r_regionkey = 1 then 10 + r_regionkey  " +
+        "when r_regionkey = 2 then 10 + r_regionkey " +
+        "when r_regionkey = 3 then 10 + r_regionkey " +
+        "when r_regionkey = 4 then 10 + r_regionkey " +
         "end as cond from region");
 
     try {
       Map<Integer, String> result = Maps.newHashMap();
       result.put(0, "null");
-      result.put(1, "one");
-      result.put(2, "two");
-      result.put(3, "three");
-      result.put(4, "four");
+      result.put(1, "11");
+      result.put(2, "12");
+      result.put(3, "13");
+      result.put(4, "14");
       int cnt = 0;
       while(res.next()) {
         assertEquals(result.get(res.getInt(1)), res.getString(2));

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
index 5e453b5..acaa205 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/CSVFile.java
@@ -19,6 +19,7 @@
 package org.apache.tajo.storage;
 
 import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -30,11 +31,15 @@ import org.apache.tajo.catalog.Column;
 import org.apache.tajo.catalog.Schema;
 import org.apache.tajo.catalog.TableMeta;
 import org.apache.tajo.catalog.statistics.TableStat;
-import org.apache.tajo.datum.*;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.ArrayDatum;
+import org.apache.tajo.datum.CharDatum;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.datum.NullDatum;
 import org.apache.tajo.exception.UnsupportedException;
 import org.apache.tajo.storage.compress.CodecPool;
 import org.apache.tajo.storage.exception.AlreadyExistsStorageException;
-import org.apache.tajo.storage.json.StorageGsonHelper;
+import org.apache.tajo.util.Bytes;
 
 import java.io.*;
 import java.util.Arrays;
@@ -43,6 +48,7 @@ public class CSVFile {
   public static final String DELIMITER = "csvfile.delimiter";
   public static final String DELIMITER_DEFAULT = "|";
   public static final byte LF = '\n';
+  public static int EOF = -1;
   private static final Log LOG = LogFactory.getLog(CSVFile.class);
 
   public static class CSVAppender extends FileAppender {
@@ -109,82 +115,104 @@ public class CSVFile {
 
     @Override
     public void addTuple(Tuple tuple) throws IOException {
-      StringBuilder sb = new StringBuilder();
       Column col;
       Datum datum;
-      for (int i = 0; i < schema.getColumnNum(); i++) {
-        datum = tuple.get(i);
-        if (enabledStats) {
-          stats.analyzeField(i, datum);
-        }
-        if (datum instanceof NullDatum) {
-        } else {
+
+      int colNum = schema.getColumnNum();
+      if(tuple instanceof LazyTuple){
+        LazyTuple  lTuple = (LazyTuple)tuple;
+        for (int i = 0; i < colNum; i++) {
           col = schema.getColumn(i);
-          switch (col.getDataType().getType()) {
-            case BOOLEAN:
-              sb.append(tuple.getBoolean(i));
-              break;
-            case BIT:
-              sb.append(new String(Base64.encodeBase64(tuple.getByte(i)
-                  .asByteArray(), false)));
-              break;
-            case BLOB:
-              sb.append(new String(Base64.encodeBase64(tuple.getBytes(i)
-                  .asByteArray(), false)));
-              break;
-            case CHAR:
-              CharDatum charDatum = tuple.getChar(i);
-              sb.append(charDatum);
-              byte[] pad = new byte[col.getDataType().getLength()-charDatum.size()];
-              sb.append(new String(pad));
-              break;
-            case TEXT:
-              TextDatum td = tuple.getText(i);
-              sb.append(td.toString());
-              break;
-            case INT2:
-              sb.append(tuple.getShort(i));
-              break;
-            case INT4:
-              sb.append(tuple.getInt(i));
-              break;
-            case INT8:
-              sb.append(tuple.getLong(i));
-              break;
-            case FLOAT4:
-              sb.append(tuple.getFloat(i));
-              break;
-            case FLOAT8:
-              sb.append(tuple.getDouble(i));
-              break;
-            case INET4:
-              sb.append(tuple.getIPv4(i));
-              break;
-            case INET6:
-              sb.append(tuple.getIPv6(i));
-            case ARRAY:
+          if (col.getDataType().getType().equals(TajoDataTypes.Type.NULL)) {
+
+          } else if (col.getDataType().getType().equals(TajoDataTypes.Type.CHAR)){
+            datum = tuple.get(i);
+            byte[] pad = new byte[col.getDataType().getLength()- datum.size()];
+            outputStream.write(lTuple.getTextBytes(i));
+            outputStream.write(pad);
+          }
+          else {
+            outputStream.write(lTuple.getTextBytes(i));
+          }
+
+          if(colNum - 1 > i){
+            outputStream.write(delimiter.getBytes());
+          }
+
+          if (enabledStats) {
+            datum = tuple.get(i);
+            stats.analyzeField(i, datum);
+          }
+        }
+      } else {
+        for (int i = 0; i < schema.getColumnNum(); i++) {
+          datum = tuple.get(i);
+          if (enabledStats) {
+            stats.analyzeField(i, datum);
+          }
+          if (datum instanceof NullDatum) {
+            outputStream.write(NullDatum.get().asTextBytes());
+          } else {
+            col = schema.getColumn(i);
+            switch (col.getDataType().getType()) {
+              case BOOLEAN:
+                outputStream.write(tuple.getBoolean(i).asTextBytes());
+                break;
+              case BIT:
+                outputStream.write(tuple.getByte(i).asTextBytes());
+                break;
+              case BLOB:
+                outputStream.write(Base64.encodeBase64(tuple.getBytes(i).asByteArray(), false));
+                break;
+              case CHAR:
+                CharDatum charDatum = tuple.getChar(i);
+                outputStream.write(charDatum.asTextBytes());
+                break;
+              case TEXT:
+                outputStream.write(tuple.getText(i).asTextBytes());
+                break;
+              case INT2:
+                outputStream.write(tuple.getShort(i).asTextBytes());
+                break;
+              case INT4:
+                outputStream.write(tuple.getInt(i).asTextBytes());
+                break;
+              case INT8:
+                outputStream.write(tuple.getLong(i).asTextBytes());
+                break;
+              case FLOAT4:
+                outputStream.write(tuple.getFloat(i).asTextBytes());
+                break;
+              case FLOAT8:
+                outputStream.write(tuple.getDouble(i).asTextBytes());
+                break;
+              case INET4:
+                outputStream.write(tuple.getIPv4(i).asTextBytes());
+                break;
+              case INET6:
+                outputStream.write(tuple.getIPv6(i).toString().getBytes());
+              case ARRAY:
             /*
              * sb.append("["); boolean first = true; ArrayDatum array =
              * (ArrayDatum) tuple.get(i); for (Datum field : array.toArray()) {
              * if (first) { first = false; } else { sb.append(delimiter); }
              * sb.append(field.asChars()); } sb.append("]");
              */
-              ArrayDatum array = (ArrayDatum) tuple.get(i);
-              sb.append(array.toJson());
-              break;
-            default:
-              throw new UnsupportedOperationException("Cannot write such field: "
-                  + tuple.get(i).type());
+                ArrayDatum array = (ArrayDatum) tuple.get(i);
+                outputStream.write(array.toJson().getBytes());
+                break;
+              default:
+                throw new UnsupportedOperationException("Cannot write such field: "
+                    + tuple.get(i).type());
+            }
+          }
+          if(colNum - 1 > i){
+            outputStream.write(delimiter.getBytes());
           }
         }
-        sb.append(delimiter);
       }
-      if (sb.length() > 0) {
-        sb.deleteCharAt(sb.length() - 1);
-      }
-      sb.append('\n');
-      outputStream.write(sb.toString().getBytes());
       // Statistical section
+      outputStream.write('\n');
       if (enabledStats) {
         stats.incrementRow();
       }
@@ -267,7 +295,7 @@ public class CSVFile {
     private boolean splittable = true;
     private long startOffset, length;
     private byte[] buf = null;
-    private String[] tuples = null;
+    private byte[][] tuples = null;
     private long[] tupleOffsets = null;
     private int currentIdx = 0, validIdx = 0;
     private byte[] tail = null;
@@ -312,7 +340,7 @@ public class CSVFile {
         is = fis;
       }
 
-      tuples = new String[0];
+      tuples = new byte[0][];
       if (targets == null) {
         targets = schema.toArray();
       }
@@ -321,8 +349,9 @@ public class CSVFile {
       for (int i = 0; i < targets.length; i++) {
         targetColumnIndexes[i] = schema.getColumnIdByName(targets[i].getColumnName());
       }
-      super.init();
 
+      super.init();
+      Arrays.sort(targetColumnIndexes);
       if (LOG.isDebugEnabled()) {
         LOG.debug("CSVScanner open:" + fragment.getPath() + "," + startOffset + "," + length +
             "," + fs.getFileStatus(fragment.getPath()).getLen());
@@ -331,7 +360,7 @@ public class CSVFile {
       if (startOffset != 0) {
         int rbyte;
         while ((rbyte = is.read()) != LF) {
-          if(rbyte == -1) break;
+          if(rbyte == EOF) break;
         }
       }
 
@@ -378,39 +407,43 @@ public class CSVFile {
       buf = new byte[bufSize];
       rbyte = is.read(buf);
 
-      if(rbyte < 0){
-        eof = true; //EOF
-        return;
-      }
-
       if (prevTailLen == 0) {
+        if(rbyte == EOF){
+          eof = true; //EOF
+          return;
+        }
+
         tail = new byte[0];
-        tuples = StringUtils.split(new String(buf, 0, rbyte), (char)LF);
+        tuples = Bytes.splitPreserveAllTokens(buf, rbyte, (char) LF);
       } else {
-        tuples = StringUtils.split(new String(tail) + new String(buf, 0, rbyte), (char)LF);
+        byte[] lastRow = ArrayUtils.addAll(tail, buf);
+        tuples = Bytes.splitPreserveAllTokens(lastRow, rbyte + tail.length, (char) LF);
         tail = null;
       }
 
       // Check tail
       if ((char) buf[rbyte - 1] != LF) {
+        // splittable bzip2 compression returned 1 byte when sync maker found
         if (isSplittable() && (fragmentable() < 1 || rbyte != bufSize)) {
-          int cnt = 0;
+          int lineFeedPos = 0;
           byte[] temp = new byte[DEFAULT_BUFFER_SIZE];
-          // Read bytes
-          while ((temp[cnt] = (byte)is.read()) != LF) {
-            cnt++;
+
+          // find line feed
+          while ((temp[lineFeedPos] = (byte)is.read()) != (byte)LF) {
+            lineFeedPos++;
           }
 
-          // Replace tuple
-          tuples[tuples.length - 1] = tuples[tuples.length - 1] + new String(temp, 0, cnt);
+          tuples[tuples.length - 1] = ArrayUtils.addAll(tuples[tuples.length - 1],
+              ArrayUtils.subarray(temp, 0, lineFeedPos));
           validIdx = tuples.length;
+
         } else {
-          tail = tuples[tuples.length - 1].getBytes();
+          tail = tuples[tuples.length - 1];
           validIdx = tuples.length - 1;
         }
       } else {
         tail = new byte[0];
-        validIdx = tuples.length;
+        validIdx = tuples.length - 1;   //remove last empty row ( .... \n .... \n  length is 3)
       }
 
      if(!isCompress()) makeTupleOffset();
@@ -421,7 +454,7 @@ public class CSVFile {
       this.tupleOffsets = new long[this.validIdx];
       for (int i = 0; i < this.validIdx; i++) {
         this.tupleOffsets[i] = curTupleOffset + this.pageStart;
-        curTupleOffset += this.tuples[i].getBytes().length + 1;//tuple byte +  1byte line feed
+        curTupleOffset += this.tuples[i].length + 1;//tuple byte +  1byte line feed
       }
     }
 
@@ -442,77 +475,13 @@ public class CSVFile {
           }
         }
 
-
         long offset = -1;
         if(!isCompress()){
           offset = this.tupleOffsets[currentIdx];
         }
 
-        String[] cells = StringUtils.splitPreserveAllTokens(tuples[currentIdx++], delimiter);
-
-        int targetLen = targets.length;
-        VTuple tuple = new VTuple(columnNum);
-        Column field;
-        tuple.setOffset(offset);
-        for (int i = 0; i < targetLen; i++) {
-          field = targets[i];
-          int tid = targetColumnIndexes[i];
-          if (cells.length <= tid) {
-            tuple.put(tid, DatumFactory.createNullDatum());
-          } else {
-            String cell = cells[tid].trim();
-
-            if (cell.equals("")) {
-              tuple.put(tid, DatumFactory.createNullDatum());
-            } else {
-              switch (field.getDataType().getType()) {
-                case BOOLEAN:
-                  tuple.put(tid, DatumFactory.createBool(cell));
-                  break;
-                case BIT:
-                  tuple.put(tid, DatumFactory.createBit(Base64.decodeBase64(cell)[0]));
-                  break;
-                case CHAR:
-                  String trimmed = cell.trim();
-                  tuple.put(tid, DatumFactory.createChar(trimmed));
-                  break;
-                case BLOB:
-                  tuple.put(tid, DatumFactory.createBlob(Base64.decodeBase64(cell)));
-                  break;
-                case INT2:
-                  tuple.put(tid, DatumFactory.createInt2(cell));
-                  break;
-                case INT4:
-                  tuple.put(tid, DatumFactory.createInt4(cell));
-                  break;
-                case INT8:
-                  tuple.put(tid, DatumFactory.createInt8(cell));
-                  break;
-                case FLOAT4:
-                  tuple.put(tid, DatumFactory.createFloat4(cell));
-                  break;
-                case FLOAT8:
-                  tuple.put(tid, DatumFactory.createFloat8(cell));
-                  break;
-                case TEXT:
-                  tuple.put(tid, DatumFactory.createText(cell));
-                  break;
-                case INET4:
-                  tuple.put(tid, DatumFactory.createInet4(cell));
-                  break;
-                case ARRAY:
-                  Datum data = StorageGsonHelper.getInstance().fromJson(cell,
-                      Datum.class);
-                  tuple.put(tid, data);
-                  break;
-                case NULL:
-                  tuple.put(tid, NullDatum.get());
-                  break;
-              }
-            }
-          }
-        }
-        return tuple;
+        byte[][] cells = Bytes.splitPreserveAllTokens(tuples[currentIdx++], delimiter, targetColumnIndexes);
+        return new LazyTuple(schema, cells, offset);
       } catch (Throwable t) {
         LOG.error("Tuple list length: " + (tuples != null ? tuples.length : 0), t);
         LOG.error("Tuple list current index: " + currentIdx, t);

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/LazyTuple.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/LazyTuple.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/LazyTuple.java
new file mode 100644
index 0000000..c10fa50
--- /dev/null
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/LazyTuple.java
@@ -0,0 +1,309 @@
+/**
+ * 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.storage;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.*;
+import org.apache.tajo.datum.exception.InvalidCastException;
+import org.apache.tajo.storage.json.StorageGsonHelper;
+
+import java.net.InetAddress;
+import java.util.Arrays;
+
+public class LazyTuple implements Tuple {
+  private long offset;
+  private Datum[] values;
+  private byte[][] textBytes;
+  private Schema schema;
+
+  public LazyTuple(Schema schema, byte[][] textBytes, long offset) {
+    this.schema = schema;
+    this.textBytes = textBytes;
+    this.values = new Datum[schema.getColumnNum()];
+    this.offset = offset;
+  }
+
+  public LazyTuple(LazyTuple tuple) {
+    this.values = new Datum[tuple.size()];
+    System.arraycopy(tuple.values, 0, values, 0, tuple.size());
+    this.offset = tuple.offset;
+    this.schema = tuple.schema;
+    this.textBytes = tuple.textBytes.clone();
+  }
+
+  @Override
+  public int size() {
+    return values.length;
+  }
+
+  @Override
+  public boolean contains(int fieldid) {
+    return textBytes[fieldid] != null || values[fieldid] != null;
+  }
+
+  @Override
+  public boolean isNull(int fieldid) {
+    return get(fieldid) instanceof NullDatum;
+  }
+
+  @Override
+  public void clear() {
+    for (int i = 0; i < values.length; i++) {
+      values[i] = null;
+      textBytes[i] = null;
+    }
+  }
+
+  //////////////////////////////////////////////////////
+  // Setter
+  //////////////////////////////////////////////////////
+  @Override
+  public void put(int fieldId, Datum value) {
+    values[fieldId] = value;
+    textBytes[fieldId] = null;
+  }
+
+  @Override
+  public void put(int fieldId, Datum[] values) {
+    for (int i = fieldId, j = 0; j < values.length; i++, j++) {
+      this.values[i] = values[j];
+    }
+    this.textBytes = new byte[values.length][];
+  }
+
+  @Override
+  public void put(int fieldId, Tuple tuple) {
+    for (int i = fieldId, j = 0; j < tuple.size(); i++, j++) {
+      values[i] = tuple.get(j);
+      textBytes[i] = null;
+    }
+  }
+
+  @Override
+  public void put(Datum[] values) {
+    System.arraycopy(values, 0, this.values, 0, size());
+    this.textBytes = new byte[values.length][];
+  }
+
+  //////////////////////////////////////////////////////
+  // Getter
+  //////////////////////////////////////////////////////
+  @Override
+  public Datum get(int fieldId) {
+    if(values[fieldId] != null)
+      return values[fieldId];
+    else if (textBytes.length > fieldId && (textBytes[fieldId] != null)) {
+      values[fieldId] = createByTextBytes(schema.getColumn(fieldId).getDataType().getType(), textBytes[fieldId]);
+      textBytes[fieldId] = null;
+    } else {
+      //values[fieldId] = NullDatum.get();
+    }
+    return values[fieldId];
+  }
+
+  @Override
+  public void setOffset(long offset) {
+    this.offset = offset;
+  }
+
+  @Override
+  public long getOffset() {
+    return this.offset;
+  }
+
+  @Override
+  public BooleanDatum getBoolean(int fieldId) {
+    return (BooleanDatum) get(fieldId);
+  }
+
+  @Override
+  public BitDatum getByte(int fieldId) {
+    return (BitDatum) get(fieldId);
+  }
+
+  @Override
+  public CharDatum getChar(int fieldId) {
+    return (CharDatum) get(fieldId);
+  }
+
+  @Override
+  public BlobDatum getBytes(int fieldId) {
+    return (BlobDatum) get(fieldId);
+  }
+
+  @Override
+  public Int2Datum getShort(int fieldId) {
+    return (Int2Datum) get(fieldId);
+  }
+
+  @Override
+  public Int4Datum getInt(int fieldId) {
+    return (Int4Datum) get(fieldId);
+  }
+
+  @Override
+  public Int8Datum getLong(int fieldId) {
+    return (Int8Datum) get(fieldId);
+  }
+
+  @Override
+  public Float4Datum getFloat(int fieldId) {
+    return (Float4Datum) get(fieldId);
+  }
+
+  @Override
+  public Float8Datum getDouble(int fieldId) {
+    return (Float8Datum) get(fieldId);
+  }
+
+  @Override
+  public Inet4Datum getIPv4(int fieldId) {
+    return (Inet4Datum) get(fieldId);
+  }
+
+  @Override
+  public byte[] getIPv4Bytes(int fieldId) {
+    return get(fieldId).asByteArray();
+  }
+
+  @Override
+  public InetAddress getIPv6(int fieldId) {
+    throw new InvalidCastException("IPv6 is unsupported yet");
+  }
+
+  @Override
+  public byte[] getIPv6Bytes(int fieldId) {
+    throw new InvalidCastException("IPv6 is unsupported yet");
+  }
+
+  @Override
+  public TextDatum getString(int fieldId) {
+    return (TextDatum) get(fieldId);
+  }
+
+  @Override
+  public TextDatum getText(int fieldId) {
+    return (TextDatum) get(fieldId);
+  }
+
+  public byte[] getTextBytes(int fieldId) {
+    if(textBytes[fieldId] != null)
+      return textBytes[fieldId];
+    else {
+      return get(fieldId).asTextBytes();
+    }
+  }
+
+  public String toString() {
+    boolean first = true;
+    StringBuilder str = new StringBuilder();
+    str.append("(");
+    Datum d;
+    for (int i = 0; i < values.length; i++) {
+      d = get(i);
+      if (d != null) {
+        if (first) {
+          first = false;
+        } else {
+          str.append(", ");
+        }
+        str.append(i)
+            .append("=>")
+            .append(d);
+      }
+    }
+    str.append(")");
+    return str.toString();
+  }
+
+  @Override
+  public int hashCode() {
+    int hashCode = 37;
+    for (int i = 0; i < values.length; i++) {
+      Datum d = get(i);
+      if (d != null) {
+        hashCode ^= (d.hashCode() * 41);
+      } else {
+        hashCode = hashCode ^ (i + 17);
+      }
+    }
+
+    return hashCode;
+  }
+
+  public Datum[] toArray() {
+    Datum[] datums = new Datum[values.length];
+    for (int i = 0; i < values.length; i++) {
+      datums[i] = get(i);
+    }
+    return datums;
+  }
+
+  @Override
+  public Tuple clone() throws CloneNotSupportedException {
+    return new LazyTuple(this);
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof LazyTuple) {
+      LazyTuple other = (LazyTuple) obj;
+      return Arrays.equals(toArray(), other.toArray());
+    } else if (obj instanceof VTuple) {
+      VTuple other = (VTuple) obj;
+      return Arrays.equals(toArray(), other.values);
+    }
+    return false;
+  }
+
+  private static Datum createByTextBytes(TajoDataTypes.Type type, byte[] val) {
+    switch (type) {
+      case BOOLEAN:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createBool(new String(val));
+      case INT2:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createInt2(new String(val));
+      case INT4:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createInt4(new String(val));
+      case INT8:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createInt8(new String(val));
+      case FLOAT4:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createFloat4(new String(val));
+      case FLOAT8:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createFloat8(new String(val));
+      case CHAR:
+        return DatumFactory.createChar(new String(val).trim());
+      case TEXT:
+        return DatumFactory.createText(val);
+      case BIT:
+        return DatumFactory.createBit(Byte.parseByte(new String(val)));
+      case BLOB:
+        return DatumFactory.createBlob(Base64.decodeBase64(val));
+      case INET4:
+        return NullDatum.isNull(val) ? NullDatum.get() : DatumFactory.createInet4(new String(val));
+      case ARRAY:
+        return NullDatum.isNull(val) ? NullDatum.get() : StorageGsonHelper.getInstance().fromJson(new String(val), Datum.class);
+      case NULL:
+        return NullDatum.get();
+      default:
+        throw new UnsupportedOperationException(type.toString());
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/VTuple.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/VTuple.java b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/VTuple.java
index eb69bdb..48d6fd1 100644
--- a/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/VTuple.java
+++ b/tajo-core/tajo-core-storage/src/main/java/org/apache/tajo/storage/VTuple.java
@@ -206,13 +206,16 @@ public class VTuple implements Tuple {
 	  return hashCode;
 	}
 
-	@Override
-	public boolean equals(Object obj) {
-		if(obj instanceof VTuple) {
-	    VTuple other = (VTuple) obj;
-	    return Arrays.equals(values, other.values);
-		}
-		
-		return false;
-	}
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof VTuple) {
+      VTuple other = (VTuple) obj;
+      return Arrays.equals(values, other.values);
+    } else if (obj instanceof LazyTuple) {
+      LazyTuple other = (LazyTuple) obj;
+      return Arrays.equals(values, other.toArray());
+    }
+
+    return false;
+  }
 }

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/53df7f45/tajo-core/tajo-core-storage/src/test/java/org/apache/tajo/storage/TestLazyTuple.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/src/test/java/org/apache/tajo/storage/TestLazyTuple.java b/tajo-core/tajo-core-storage/src/test/java/org/apache/tajo/storage/TestLazyTuple.java
new file mode 100644
index 0000000..3ca0789
--- /dev/null
+++ b/tajo-core/tajo-core-storage/src/test/java/org/apache/tajo/storage/TestLazyTuple.java
@@ -0,0 +1,212 @@
+/**
+ * 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.storage;
+
+
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes;
+import org.apache.tajo.datum.DatumFactory;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.util.Bytes;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class TestLazyTuple {
+
+  Schema schema;
+  byte[][] textRow;
+
+  @Before
+  public void setUp() {
+    schema = new Schema();
+    schema.addColumn("col1", TajoDataTypes.Type.BOOLEAN);
+    schema.addColumn("col2", TajoDataTypes.Type.BIT);
+    schema.addColumn("col3", TajoDataTypes.Type.CHAR, 7);
+    schema.addColumn("col4", TajoDataTypes.Type.INT2);
+    schema.addColumn("col5", TajoDataTypes.Type.INT4);
+    schema.addColumn("col6", TajoDataTypes.Type.INT8);
+    schema.addColumn("col7", TajoDataTypes.Type.FLOAT4);
+    schema.addColumn("col8", TajoDataTypes.Type.FLOAT8);
+    schema.addColumn("col9", TajoDataTypes.Type.TEXT);
+    schema.addColumn("col10", TajoDataTypes.Type.BLOB);
+    schema.addColumn("col11", TajoDataTypes.Type.INET4);
+    schema.addColumn("col12", TajoDataTypes.Type.NULL);
+
+    StringBuilder sb = new StringBuilder();
+    sb.append(DatumFactory.createBool(true)).append('|');
+    sb.append(new String(DatumFactory.createBit((byte) 0x99).asTextBytes())).append('|');
+    sb.append(DatumFactory.createChar("str")).append('|');
+    sb.append(DatumFactory.createInt2((short) 17)).append('|');
+    sb.append(DatumFactory.createInt4(59)).append('|');
+    sb.append(DatumFactory.createInt8(23l)).append('|');
+    sb.append(DatumFactory.createFloat4(77.9f)).append('|');
+    sb.append(DatumFactory.createFloat8(271.9f)).append('|');
+    sb.append(DatumFactory.createText("str2")).append('|');
+    sb.append(DatumFactory.createBlob("jinho".getBytes())).append('|');
+    sb.append(DatumFactory.createInet4("192.168.0.1")).append('|');
+    sb.append(NullDatum.get());
+
+    textRow = Bytes.splitPreserveAllTokens(sb.toString().getBytes(), '|');
+  }
+
+  @Test
+  public void testGetDatum() {
+
+    LazyTuple t1 = new LazyTuple(schema, textRow, -1);
+    assertEquals(DatumFactory.createBool(true), t1.get(0));
+    assertEquals(DatumFactory.createBit((byte) 0x99), t1.get(1));
+    assertEquals(DatumFactory.createChar("str"), t1.get(2));
+    assertEquals(DatumFactory.createInt2((short) 17), t1.get(3));
+    assertEquals(DatumFactory.createInt4(59), t1.get(4));
+    assertEquals(DatumFactory.createInt8(23l), t1.get(5));
+    assertEquals(DatumFactory.createFloat4(77.9f), t1.get(6));
+    assertEquals(DatumFactory.createFloat8(271.9f), t1.get(7));
+    assertEquals(DatumFactory.createText("str2"), t1.get(8));
+    assertEquals(DatumFactory.createBlob("jinho".getBytes()), t1.get(9));
+    assertEquals(DatumFactory.createInet4("192.168.0.1"), t1.get(10));
+    assertEquals(NullDatum.get(), t1.get(11));
+  }
+
+  @Test
+  public void testContain() {
+    int colNum = schema.getColumnNum();
+
+    LazyTuple t1 = new LazyTuple(schema, new byte[colNum][], -1);
+    t1.put(0, DatumFactory.createInt4(1));
+    t1.put(3, DatumFactory.createInt4(1));
+    t1.put(7, DatumFactory.createInt4(1));
+
+    assertTrue(t1.contains(0));
+    assertFalse(t1.contains(1));
+    assertFalse(t1.contains(2));
+    assertTrue(t1.contains(3));
+    assertFalse(t1.contains(4));
+    assertFalse(t1.contains(5));
+    assertFalse(t1.contains(6));
+    assertTrue(t1.contains(7));
+    assertFalse(t1.contains(8));
+    assertFalse(t1.contains(9));
+    assertFalse(t1.contains(10));
+    assertFalse(t1.contains(11));
+  }
+
+  @Test
+  public void testPut() {
+    int colNum = schema.getColumnNum();
+    LazyTuple t1 = new LazyTuple(schema, new byte[colNum][], -1);
+    t1.put(0, DatumFactory.createText("str"));
+    t1.put(1, DatumFactory.createInt4(2));
+    t1.put(11, DatumFactory.createFloat4(0.76f));
+
+    assertTrue(t1.contains(0));
+    assertTrue(t1.contains(1));
+
+    assertEquals(t1.getString(0).toString(), "str");
+    assertEquals(t1.getInt(1).asInt4(), 2);
+    assertTrue(t1.getFloat(11).asFloat4() == 0.76f);
+  }
+
+  @Test
+  public void testEquals() {
+    int colNum = schema.getColumnNum();
+    LazyTuple t1 = new LazyTuple(schema, new byte[colNum][], -1);
+    LazyTuple t2 = new LazyTuple(schema, new byte[colNum][], -1);
+
+    t1.put(0, DatumFactory.createInt4(1));
+    t1.put(1, DatumFactory.createInt4(2));
+    t1.put(3, DatumFactory.createInt4(2));
+
+    t2.put(0, DatumFactory.createInt4(1));
+    t2.put(1, DatumFactory.createInt4(2));
+    t2.put(3, DatumFactory.createInt4(2));
+
+    assertEquals(t1, t2);
+
+    Tuple t3 = new VTuple(colNum);
+    t3.put(0, DatumFactory.createInt4(1));
+    t3.put(1, DatumFactory.createInt4(2));
+    t3.put(3, DatumFactory.createInt4(2));
+    assertEquals(t1, t3);
+    assertEquals(t2, t3);
+
+    LazyTuple t4 = new LazyTuple(schema, new byte[colNum][], -1);
+    assertNotSame(t1, t4);
+  }
+
+  @Test
+  public void testHashCode() {
+    int colNum = schema.getColumnNum();
+    LazyTuple t1 = new LazyTuple(schema, new byte[colNum][], -1);
+    LazyTuple t2 = new LazyTuple(schema, new byte[colNum][], -1);
+
+    t1.put(0, DatumFactory.createInt4(1));
+    t1.put(1, DatumFactory.createInt4(2));
+    t1.put(3, DatumFactory.createInt4(2));
+    t1.put(4, DatumFactory.createText("str"));
+
+    t2.put(0, DatumFactory.createInt4(1));
+    t2.put(1, DatumFactory.createInt4(2));
+    t2.put(3, DatumFactory.createInt4(2));
+    t2.put(4, DatumFactory.createText("str"));
+
+    assertEquals(t1.hashCode(), t2.hashCode());
+
+    Tuple t3 = new VTuple(colNum);
+    t3.put(0, DatumFactory.createInt4(1));
+    t3.put(1, DatumFactory.createInt4(2));
+    t3.put(3, DatumFactory.createInt4(2));
+    t3.put(4, DatumFactory.createText("str"));
+    assertEquals(t1.hashCode(), t3.hashCode());
+    assertEquals(t2.hashCode(), t3.hashCode());
+
+    Tuple t4 = new VTuple(5);
+    t4.put(0, DatumFactory.createInt4(1));
+    t4.put(1, DatumFactory.createInt4(2));
+    t4.put(4, DatumFactory.createInt4(2));
+
+    assertNotSame(t1.hashCode(), t4.hashCode());
+  }
+
+  @Test
+  public void testPutTuple() {
+    int colNum = schema.getColumnNum();
+    LazyTuple t1 = new LazyTuple(schema, new byte[colNum][], -1);
+
+    t1.put(0, DatumFactory.createInt4(1));
+    t1.put(1, DatumFactory.createInt4(2));
+    t1.put(2, DatumFactory.createInt4(3));
+
+
+    Schema schema2 = new Schema();
+    schema2.addColumn("col1", TajoDataTypes.Type.INT8);
+    schema2.addColumn("col2", TajoDataTypes.Type.INT8);
+
+    LazyTuple t2 = new LazyTuple(schema2, new byte[schema2.getColumnNum()][], -1);
+    t2.put(0, DatumFactory.createInt4(4));
+    t2.put(1, DatumFactory.createInt4(5));
+
+    t1.put(3, t2);
+
+    for (int i = 0; i < 5; i++) {
+      assertEquals(i + 1, t1.get(i).asInt4());
+    }
+  }
+}


Mime
View raw message