You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tajo.apache.org by hy...@apache.org on 2013/12/30 10:17:58 UTC

[2/6] TAJO-456: Separate tajo-jdbc and tajo-client from tajo-core-backend. (hyunsik)

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-core/tajo-core-pullserver/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-pullserver/pom.xml b/tajo-core/tajo-core-pullserver/pom.xml
index d4f50f4..8c6d4fe 100644
--- a/tajo-core/tajo-core-pullserver/pom.xml
+++ b/tajo-core/tajo-core-pullserver/pom.xml
@@ -51,12 +51,12 @@
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-yarn-server-nodemanager</artifactId>
-      <scope>compile</scope>
+      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-yarn-common</artifactId>
-      <scope>compile</scope>
+      <scope>provided</scope>
     </dependency>
     <dependency>
       <groupId>io.netty</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-core/tajo-core-pullserver/src/main/java/org/apache/tajo/storage/Tuple.java
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-pullserver/src/main/java/org/apache/tajo/storage/Tuple.java b/tajo-core/tajo-core-pullserver/src/main/java/org/apache/tajo/storage/Tuple.java
new file mode 100644
index 0000000..711666f
--- /dev/null
+++ b/tajo-core/tajo-core-pullserver/src/main/java/org/apache/tajo/storage/Tuple.java
@@ -0,0 +1,80 @@
+/**
+ * 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.datum.*;
+
+import java.net.InetAddress;
+
+public interface Tuple extends Cloneable {
+
+  public int size();
+
+  public boolean contains(int fieldid);
+
+  public boolean isNull(int fieldid);
+
+  public void clear();
+
+  public void put(int fieldId, Datum value);
+
+  public void put(int fieldId, Datum [] values);
+
+  public void put(int fieldId, Tuple tuple);
+
+  public void put(Datum [] values);
+
+  public Datum get(int fieldId);
+
+  public void setOffset(long offset);
+
+  public long getOffset();
+
+  public BooleanDatum getBoolean(int fieldId);
+
+  public BitDatum getByte(int fieldId);
+
+  public CharDatum getChar(int fieldId);
+
+  public BlobDatum getBytes(int fieldId);
+
+  public Int2Datum getShort(int fieldId);
+
+  public Int4Datum getInt(int fieldId);
+
+  public Int8Datum getLong(int fieldId);
+
+  public Float4Datum getFloat(int fieldId);
+
+  public Float8Datum getDouble(int fieldId);
+
+  public Inet4Datum getIPv4(int fieldId);
+
+  public byte [] getIPv4Bytes(int fieldId);
+
+  public InetAddress getIPv6(int fieldId);
+
+  public byte [] getIPv6Bytes(int fieldId);
+
+  public TextDatum getString(int fieldId);
+
+  public TextDatum getText(int fieldId);
+
+  public Tuple clone() throws CloneNotSupportedException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-core/tajo-core-storage/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-core/tajo-core-storage/pom.xml b/tajo-core/tajo-core-storage/pom.xml
index 176dd14..26a6e94 100644
--- a/tajo-core/tajo-core-storage/pom.xml
+++ b/tajo-core/tajo-core-storage/pom.xml
@@ -170,41 +170,7 @@
     </dependency>
     <dependency>
       <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-minicluster</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
       <artifactId>hadoop-hdfs</artifactId>
-      <type>test-jar</type>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-yarn-api</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-yarn-common</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-yarn-server-nodemanager</artifactId>
-      <scope>compile</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-yarn-server-resourcemanager</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-yarn-server-common</artifactId>
-      <scope>test</scope>
-    </dependency>
-    <dependency>
-      <groupId>org.apache.hadoop</groupId>
-      <artifactId>hadoop-yarn-server-tests</artifactId>
-      <type>test-jar</type>
-      <scope>test</scope>
     </dependency>
 
     <dependency>
@@ -214,6 +180,7 @@
     <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>commons-logging</groupId>
@@ -227,11 +194,6 @@
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.mockito</groupId>
-      <artifactId>mockito-core</artifactId>
-      <scope>test</scope>
-    </dependency>
 
     <dependency>
       <groupId>com.google.code.gson</groupId>
@@ -287,7 +249,7 @@
             <executions>
               <execution>
                 <!-- builds source jars and attaches them to the project for publishing -->
-                <id>hadoop-java-sources</id>
+                <id>tajo-java-sources</id>
                 <phase>package</phase>
                 <goals>
                   <goal>jar-no-fork</goal>

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-dist/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-dist/pom.xml b/tajo-dist/pom.xml
index 562f21a..0712d01 100644
--- a/tajo-dist/pom.xml
+++ b/tajo-dist/pom.xml
@@ -102,11 +102,17 @@
                       run cp -r $ROOT/tajo-common/target/tajo-common-${project.version}/* .
                       run cp -r $ROOT/tajo-rpc/target/tajo-rpc-${project.version}/* .
                       run cp -r $ROOT/tajo-algebra/target/tajo-algebra-${project.version}/* .
+                      run cp -r $ROOT/tajo-client/target/tajo-client-${project.version}/* .
                       run cp -r $ROOT/tajo-catalog/target/tajo-catalog-${project.version}/* .
                       run cp -r $ROOT/tajo-core/target/tajo-core-${project.version}/* .
                       run cp -r ${project.basedir}/src/main/bin .
                       run cp -r ${project.basedir}/src/main/conf .
                       run rm -rf lib/tajo-*-${project.version}.jar
+
+                      run mkdir -p share/jdbc-dist
+                      run cp -r $ROOT/tajo-jdbc/target/tajo-jdbc-${project.version}.jar ./share/jdbc-dist
+                      run cp -r $ROOT/tajo-jdbc/target/lib/* ./share/jdbc-dist
+
                       echo
                       echo "Tajo dist layout available at: ${project.build.directory}/tajo-${project.version}"
                       echo

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-jdbc/pom.xml
----------------------------------------------------------------------
diff --git a/tajo-jdbc/pom.xml b/tajo-jdbc/pom.xml
new file mode 100644
index 0000000..52f9bbb
--- /dev/null
+++ b/tajo-jdbc/pom.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <artifactId>tajo-project</artifactId>
+    <groupId>org.apache.tajo</groupId>
+    <version>0.8.0-SNAPSHOT</version>
+    <relativePath>../tajo-project</relativePath>
+  </parent>
+  <artifactId>tajo-jdbc</artifactId>
+  <packaging>jar</packaging>
+  <name>Tajo JDBC Driver</name>
+  <version>0.8.0-SNAPSHOT</version>
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+  </properties>
+
+  <repositories>
+    <repository>
+      <id>repository.jboss.org</id>
+      <url>https://repository.jboss.org/nexus/content/repositories/releases/
+      </url>
+      <snapshots>
+        <enabled>false</enabled>
+      </snapshots>
+    </repository>
+  </repositories>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>1.6</source>
+          <target>1.6</target>
+          <encoding>${project.build.sourceEncoding}</encoding>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-dependencies</id>
+            <phase>package</phase>
+            <goals>
+              <goal>copy-dependencies</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.directory}/lib</outputDirectory>
+              <overWriteReleases>false</overWriteReleases>
+              <overWriteSnapshots>false</overWriteSnapshots>
+              <overWriteIfNewer>true</overWriteIfNewer>
+              <includeGroupIds>org.apache.tajo,joda-time</includeGroupIds>
+              <excludeScope>provided</excludeScope>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.tajo</groupId>
+      <artifactId>tajo-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tajo</groupId>
+      <artifactId>tajo-catalog-common</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tajo</groupId>
+      <artifactId>tajo-core-storage</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tajo</groupId>
+      <artifactId>tajo-rpc</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.tajo</groupId>
+      <artifactId>tajo-client</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-common</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hadoop</groupId>
+      <artifactId>hadoop-hdfs</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>docs</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <executions>
+              <execution>
+                <!-- build javadoc jars per jar for publishing to maven -->
+                <id>module-javadocs</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+                <configuration>
+                  <destDir>${project.build.directory}</destDir>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>src</id>
+      <activation>
+        <activeByDefault>false</activeByDefault>
+      </activation>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <executions>
+              <execution>
+                <!-- builds source jars and attaches them to the project for publishing -->
+                <id>tajo-java-sources</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>jar-no-fork</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <dependencyLocationsEnabled>false</dependencyLocationsEnabled>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-report-plugin</artifactId>
+        <version>2.15</version>
+      </plugin>
+    </plugins>
+  </reporting>
+</project>
+

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/MetaDataTuple.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/MetaDataTuple.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/MetaDataTuple.java
new file mode 100644
index 0000000..ba32962
--- /dev/null
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/MetaDataTuple.java
@@ -0,0 +1,192 @@
+package org.apache.tajo.jdbc; /**
+ * 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.
+ */
+
+import org.apache.tajo.datum.*;
+import org.apache.tajo.exception.UnsupportedException;
+import org.apache.tajo.storage.Tuple;
+
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+public class MetaDataTuple implements Tuple {
+  List<Datum> values = new ArrayList<Datum>();
+
+  public MetaDataTuple(int size) {
+    values = new ArrayList<Datum>(size);
+    for(int i = 0; i < size; i++) {
+      values.add(NullDatum.get());
+    }
+  }
+
+  @Override
+  public int size() {
+    return values.size();
+  }
+
+  @Override
+  public boolean contains(int fieldid) {
+    return false;
+  }
+
+  @Override
+  public boolean isNull(int fieldid) {
+    return values.get(fieldid) == null || values.get(fieldid) instanceof NullDatum;
+  }
+
+  @Override
+  public void clear() {
+    values.clear();
+  }
+
+  @Override
+  public void put(int fieldId, Datum value) {
+    values.set(fieldId, value);
+  }
+
+  @Override
+  public void put(int fieldId, Datum[] values) {
+    throw new UnsupportedException("put");
+  }
+
+  @Override
+  public void put(int fieldId, Tuple tuple) {
+    throw new UnsupportedException("put");
+  }
+
+  @Override
+  public void put(Datum[] values) {
+    throw new UnsupportedException("put");
+  }
+
+  @Override
+  public Datum get(int fieldId) {
+    return getText(fieldId);
+  }
+
+  @Override
+  public void setOffset(long offset) {
+    throw new UnsupportedException("setOffset");
+  }
+
+  @Override
+  public long getOffset() {
+    throw new UnsupportedException("getOffset");
+  }
+
+  @Override
+  public BooleanDatum getBoolean(int fieldId) {
+    throw new UnsupportedException("getBoolean");
+  }
+
+  @Override
+  public BitDatum getByte(int fieldId) {
+    throw new UnsupportedException("getByte");
+  }
+
+  @Override
+  public CharDatum getChar(int fieldId) {
+    throw new UnsupportedException("getBoolean");
+  }
+
+  @Override
+  public BlobDatum getBytes(int fieldId) {
+    throw new UnsupportedException("BlobDatum");
+  }
+
+  @Override
+  public Int2Datum getShort(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new Int2Datum((short)Integer.parseInt(values.get(fieldId).toString()));
+  }
+
+  @Override
+  public Int4Datum getInt(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new Int4Datum(Integer.parseInt(values.get(fieldId).toString()));
+  }
+
+  @Override
+  public Int8Datum getLong(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new Int8Datum(Long.parseLong(values.get(fieldId).toString()));
+  }
+
+  @Override
+  public Float4Datum getFloat(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new Float4Datum(Float.parseFloat(values.get(fieldId).toString()));
+  }
+
+  @Override
+  public Float8Datum getDouble(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new Float8Datum(Float.parseFloat(values.get(fieldId).toString()));
+  }
+
+  @Override
+  public Inet4Datum getIPv4(int fieldId) {
+    throw new UnsupportedException("getIPv4");
+  }
+
+  @Override
+  public byte[] getIPv4Bytes(int fieldId) {
+    throw new UnsupportedException("getIPv4Bytes");
+  }
+
+  @Override
+  public InetAddress getIPv6(int fieldId) {
+    throw new UnsupportedException("getIPv6");
+  }
+
+  @Override
+  public byte[] getIPv6Bytes(int fieldId) {
+    throw new UnsupportedException("getIPv6Bytes");
+  }
+
+  @Override
+  public TextDatum getString(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new TextDatum(values.get(fieldId).toString());
+  }
+
+  @Override
+  public TextDatum getText(int fieldId) {
+    if(isNull(fieldId)) {
+      return null;
+    }
+    return new TextDatum(values.get(fieldId).toString());
+  }
+
+  @Override
+  public Tuple clone() throws CloneNotSupportedException {
+    throw new UnsupportedException("clone");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
new file mode 100644
index 0000000..b751d5d
--- /dev/null
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoConnection.java
@@ -0,0 +1,398 @@
+package org.apache.tajo.jdbc; /**
+ * 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.
+ */
+
+import org.apache.tajo.client.TajoClient;
+import org.apache.tajo.conf.TajoConf;
+
+import java.sql.*;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class TajoConnection implements Connection {
+  private TajoClient tajoClient;
+
+  private String databaseName;
+
+  private AtomicBoolean closed = new AtomicBoolean(true);
+
+  private String uri;
+
+  public TajoConnection(String uri, Properties properties) throws SQLException {
+    if (!uri.startsWith(TajoDriver.TAJO_JDBC_URL_PREFIX)) {
+      throw new SQLException("Invalid URL: " + uri, "TAJO-001");
+    }
+
+    this.uri = uri;
+
+    // remove prefix
+    uri = uri.substring(TajoDriver.TAJO_JDBC_URL_PREFIX.length());
+
+
+    if (uri.isEmpty()) {
+      throw new SQLException("Invalid URL: " + uri, "TAJO-001");
+    }
+
+    // parse uri
+    // form: hostname:port/databasename
+    String[] parts = uri.split("/");
+    if(parts.length == 0 || parts[0].trim().isEmpty()) {
+      throw new SQLException("Invalid URL(No tajo master's host:port): " + uri, "TAJO-001");
+    }
+    String[] hostAndPort = parts[0].trim().split(":");
+    String host = hostAndPort[0];
+    int port = 0;
+    try {
+      port = Integer.parseInt(hostAndPort[1]);
+    } catch (Exception e) {
+      throw new SQLException("Invalid URL(Wrong tajo master's host:port): " + uri, "TAJO-001");
+    }
+
+    if(parts.length > 1) {
+      String[] tokens = parts[1].split("\\?");
+      databaseName = tokens[0].trim();
+      if(tokens.length > 1) {
+        String[] extraParamTokens = tokens[1].split("&");
+        for(String eachExtraParam: extraParamTokens) {
+          String[] paramTokens = eachExtraParam.split("=");
+          String extraParamKey = paramTokens[0];
+          String extraParamValue = paramTokens[1];
+        }
+      }
+    }
+
+    TajoConf tajoConf = new TajoConf();
+
+    tajoConf.setVar(TajoConf.ConfVars.TAJO_MASTER_CLIENT_RPC_ADDRESS, host + ":" + port);
+
+    if(properties != null) {
+      for(Map.Entry<Object, Object> entry: properties.entrySet()) {
+        tajoConf.set(entry.getKey().toString(), entry.getValue().toString());
+      }
+    }
+
+    try {
+      tajoClient = new TajoClient(tajoConf);
+    } catch (Exception e) {
+      throw new SQLException("Can't create tajo client:" + e.getMessage(), "TAJO-002");
+    }
+    closed.set(false);
+  }
+
+  public String getUri() {
+    return uri;
+  }
+
+  public TajoClient getTajoClient() {
+    return tajoClient;
+  }
+
+  @Override
+  public void clearWarnings() throws SQLException {
+  }
+
+  @Override
+  public void close() throws SQLException {
+    if(!closed.get()) {
+      if(tajoClient != null) {
+        tajoClient.close();
+      }
+
+      closed.set(true);
+    }
+  }
+
+  @Override
+  public void commit() throws SQLException {
+    throw new SQLFeatureNotSupportedException("commit");
+  }
+
+  @Override
+  public Array createArrayOf(String arg0, Object[] arg1) throws SQLException {
+    throw new SQLFeatureNotSupportedException("createArrayOf");
+  }
+
+  @Override
+  public Blob createBlob() throws SQLException {
+    throw new SQLFeatureNotSupportedException("createBlob");
+  }
+
+  @Override
+  public Clob createClob() throws SQLException {
+    throw new SQLFeatureNotSupportedException("createClob");
+  }
+
+  @Override
+  public NClob createNClob() throws SQLException {
+    throw new SQLFeatureNotSupportedException("createNClob");
+  }
+
+  @Override
+  public SQLXML createSQLXML() throws SQLException {
+    throw new SQLFeatureNotSupportedException("createSQLXML");
+  }
+
+  @Override
+  public Statement createStatement() throws SQLException {
+    if (isClosed()) {
+      throw new SQLException("Can't create Statement, connection is closed");
+    }
+    return new TajoStatement(tajoClient);
+  }
+
+  @Override
+  public Statement createStatement(int resultSetType, int resultSetConcurrency)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("createStatement");
+  }
+
+  @Override
+  public Statement createStatement(int resultSetType, int resultSetConcurrency,
+                                   int resultSetHoldability) throws SQLException {
+    throw new SQLFeatureNotSupportedException("createStatement");
+  }
+
+  @Override
+  public Struct createStruct(String typeName, Object[] attributes)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("createStruct");
+  }
+
+  @Override
+  public boolean getAutoCommit() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public String getCatalog() throws SQLException {
+    return "";
+  }
+
+  @Override
+  public Properties getClientInfo() throws SQLException {
+    throw new SQLFeatureNotSupportedException("getClientInfo");
+  }
+
+  @Override
+  public String getClientInfo(String name) throws SQLException {
+    throw new SQLFeatureNotSupportedException("getClientInfo");
+  }
+
+  @Override
+  public int getHoldability() throws SQLException {
+    throw new SQLFeatureNotSupportedException("getHoldability");
+  }
+
+  @Override
+  public DatabaseMetaData getMetaData() throws SQLException {
+    return new TajoDatabaseMetaData(this);
+  }
+
+  @Override
+  public int getTransactionIsolation() throws SQLException {
+    return Connection.TRANSACTION_NONE;
+  }
+
+  @Override
+  public Map<String, Class<?>> getTypeMap() throws SQLException {
+    throw new SQLFeatureNotSupportedException("getTypeMap");
+  }
+
+  @Override
+  public SQLWarning getWarnings() throws SQLException {
+    throw new SQLFeatureNotSupportedException("getWarnings");
+  }
+
+  @Override
+  public boolean isClosed() throws SQLException {
+    return closed.get();
+  }
+
+  @Override
+  public boolean isReadOnly() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean isValid(int timeout) throws SQLException {
+    throw new SQLFeatureNotSupportedException("isValid");
+  }
+
+  @Override
+  public String nativeSQL(String sql) throws SQLException {
+    throw new SQLFeatureNotSupportedException("nativeSQL");
+  }
+
+  @Override
+  public CallableStatement prepareCall(String sql) throws SQLException {
+    throw new SQLFeatureNotSupportedException("prepareCall");
+  }
+
+  @Override
+  public CallableStatement prepareCall(String sql, int resultSetType,
+                                       int resultSetConcurrency) throws SQLException {
+    throw new SQLFeatureNotSupportedException("prepareCall");
+  }
+
+  @Override
+  public CallableStatement prepareCall(String sql, int resultSetType,
+                                       int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+    throw new SQLFeatureNotSupportedException("prepareCall");
+  }
+
+  @Override
+  public PreparedStatement prepareStatement(String sql) throws SQLException {
+    return new TajoPreparedStatement(tajoClient, sql);
+  }
+
+  @Override
+  public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+      throws SQLException {
+    return new TajoPreparedStatement(tajoClient, sql);
+  }
+
+  @Override
+  public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("prepareStatement");
+  }
+
+  @Override
+  public PreparedStatement prepareStatement(String sql, String[] columnNames)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("prepareStatement");
+  }
+
+  @Override
+  public PreparedStatement prepareStatement(String sql, int resultSetType,
+                                            int resultSetConcurrency) throws SQLException {
+    return new TajoPreparedStatement(tajoClient, sql);
+  }
+
+  @Override
+  public PreparedStatement prepareStatement(String sql, int resultSetType,
+                                            int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+    throw new SQLFeatureNotSupportedException("prepareStatement");
+  }
+
+  @Override
+  public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+    throw new SQLFeatureNotSupportedException("releaseSavepoint");
+  }
+
+  @Override
+  public void rollback() throws SQLException {
+    throw new SQLFeatureNotSupportedException("rollback");
+  }
+
+  @Override
+  public void rollback(Savepoint savepoint) throws SQLException {
+    throw new SQLFeatureNotSupportedException("rollback");
+  }
+
+  @Override
+  public void setAutoCommit(boolean autoCommit) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setAutoCommit");
+  }
+
+  @Override
+  public void setCatalog(String catalog) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setCatalog");
+  }
+
+  @Override
+  public void setClientInfo(Properties properties)
+      throws SQLClientInfoException {
+    throw new UnsupportedOperationException("setClientInfo");
+  }
+
+  @Override
+  public void setClientInfo(String name, String value)
+      throws SQLClientInfoException {
+    throw new UnsupportedOperationException("setClientInfo");
+  }
+
+  @Override
+  public void setHoldability(int holdability) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setHoldability");
+  }
+
+  @Override
+  public void setReadOnly(boolean readOnly) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setReadOnly");
+  }
+
+  @Override
+  public Savepoint setSavepoint() throws SQLException {
+    throw new SQLFeatureNotSupportedException("setSavepoint");
+  }
+
+  @Override
+  public Savepoint setSavepoint(String name) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setSavepoint");
+  }
+
+  @Override
+  public void setTransactionIsolation(int level) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setTransactionIsolation");
+  }
+
+  @Override
+  public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+    throw new SQLFeatureNotSupportedException("setTypeMap");
+  }
+
+  @Override
+  public <T> T unwrap(Class<T> tClass) throws SQLException {
+    if (isWrapperFor(tClass)) {
+      return (T) this;
+    }
+    throw new SQLException("No wrapper for " + tClass);
+  }
+
+  @Override
+  public boolean isWrapperFor(Class<?> tClass) throws SQLException {
+    return tClass.isInstance(this);
+  }
+
+  public void abort(Executor executor) throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("abort not supported");
+  }
+
+  public int getNetworkTimeout() throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("getNetworkTimeout not supported");
+  }
+
+  public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("setNetworkTimeout not supported");
+  }
+
+  public String getSchema() throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("getSchema not supported");
+  }
+
+  public void setSchema(String schema) throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("setSchema not supported");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
new file mode 100644
index 0000000..e868701
--- /dev/null
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDatabaseMetaData.java
@@ -0,0 +1,1196 @@
+package org.apache.tajo.jdbc; /**
+ * 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.
+ */
+
+import org.apache.tajo.TajoConstants;
+import org.apache.tajo.catalog.Column;
+import org.apache.tajo.catalog.TableDesc;
+import org.apache.tajo.client.ResultSetUtil;
+import org.apache.tajo.client.TajoClient;
+import org.apache.tajo.common.TajoDataTypes.Type;
+import org.apache.tajo.datum.NullDatum;
+import org.apache.tajo.datum.TextDatum;
+
+import java.sql.*;
+import java.util.*;
+
+/**
+ * TajoDatabaseMetaData.
+ */
+public class TajoDatabaseMetaData implements DatabaseMetaData {
+  private static final char SEARCH_STRING_ESCAPE = '\\';
+
+  private final TajoConnection conn;
+
+  public TajoDatabaseMetaData(TajoConnection conn) {
+    this.conn = conn;
+  }
+
+  @Override
+  public boolean allProceduresAreCallable()
+      throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean allTablesAreSelectable()
+      throws SQLException {
+    return true;
+  }
+
+  @Override
+  public String getURL()
+      throws SQLException {
+    return conn.getUri();
+  }
+
+  @Override
+  public String getUserName()
+      throws SQLException {
+    return "tajo";
+  }
+
+  @Override
+  public boolean isReadOnly()
+      throws SQLException {
+    return true;
+  }
+
+  @Override
+  public String getDatabaseProductName()
+      throws SQLException {
+    return "Tajo";
+  }
+
+  @Override
+  public String getDatabaseProductVersion()
+      throws SQLException {
+    //TODO get from tajo master
+    return TajoConstants.TAJO_VERSION;
+  }
+
+  @Override
+  public String getDriverName()
+      throws SQLException {
+    return "tajo";
+  }
+
+  @Override
+  public String getDriverVersion()
+      throws SQLException {
+    return TajoDriver.MAJOR_VERSION + "." + TajoDriver.MINOR_VERSION;
+  }
+
+  @Override
+  public int getDriverMajorVersion() {
+    return TajoDriver.MAJOR_VERSION;
+  }
+
+  @Override
+  public int getDriverMinorVersion() {
+    return TajoDriver.MINOR_VERSION;
+  }
+
+  @Override
+  public String getIdentifierQuoteString()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getIdentifierQuoteString not supported");
+  }
+
+  @Override
+  public String getSQLKeywords()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getSQLKeywords not supported");
+  }
+
+  @Override
+  public String getNumericFunctions()
+      throws SQLException {
+    return "";
+  }
+
+  @Override
+  public String getStringFunctions()
+      throws SQLException {
+    return "";
+  }
+
+  @Override
+  public String getSystemFunctions()
+      throws SQLException {
+    return "";
+  }
+
+  @Override
+  public String getTimeDateFunctions()
+      throws SQLException {
+    return "";
+  }
+
+  @Override
+  public String getSearchStringEscape()
+      throws SQLException {
+    return "\\";
+  }
+
+  @Override
+  public String getExtraNameCharacters()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getExtraNameCharacters not supported");
+  }
+
+  @Override
+  public String getSchemaTerm()
+      throws SQLException {
+    return "";
+  }
+
+  @Override
+  public String getProcedureTerm()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getProcedureTerm not supported");
+  }
+
+  @Override
+  public String getCatalogTerm()
+      throws SQLException {
+    return "database";
+  }
+
+  @Override
+  public String getCatalogSeparator()
+      throws SQLException {
+    return ".";
+  }
+
+  @Override
+  public int getMaxBinaryLiteralLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxBinaryLiteralLength not supported");
+  }
+
+  @Override
+  public int getMaxCharLiteralLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxCharLiteralLength not supported");
+  }
+
+  @Override
+  public int getMaxColumnNameLength()
+      throws SQLException {
+    return 128;
+  }
+
+  @Override
+  public int getMaxColumnsInGroupBy()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxColumnsInGroupBy not supported");
+  }
+
+  @Override
+  public int getMaxColumnsInIndex()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxColumnsInIndex not supported");
+  }
+
+  @Override
+  public int getMaxColumnsInOrderBy()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxColumnsInOrderBy not supported");
+  }
+
+  @Override
+  public int getMaxColumnsInSelect()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxColumnsInSelect not supported");
+  }
+
+  @Override
+  public int getMaxColumnsInTable()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxColumnsInTable not supported");
+  }
+
+  @Override
+  public int getMaxConnections()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxConnections not supported");
+  }
+
+  @Override
+  public int getMaxCursorNameLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxCursorNameLength not supported");
+  }
+
+  @Override
+  public int getMaxIndexLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxIndexLength not supported");
+  }
+
+  @Override
+  public int getMaxSchemaNameLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxSchemaNameLength not supported");
+  }
+
+  @Override
+  public int getMaxProcedureNameLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxProcedureNameLength not supported");
+  }
+
+  @Override
+  public int getMaxCatalogNameLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxCatalogNameLength not supported");
+  }
+
+  @Override
+  public int getMaxRowSize()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxRowSize not supported");
+  }
+
+  @Override
+  public boolean doesMaxRowSizeIncludeBlobs()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("doesMaxRowSizeIncludeBlobs not supported");
+  }
+
+  @Override
+  public int getMaxStatementLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxStatementLength not supported");
+  }
+
+  @Override
+  public int getMaxStatements()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxStatements not supported");
+  }
+
+  @Override
+  public int getMaxTableNameLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxTableNameLength not supported");
+  }
+
+  @Override
+  public int getMaxTablesInSelect()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxTablesInSelect not supported");
+  }
+
+  @Override
+  public int getMaxUserNameLength()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getMaxUserNameLength not supported");
+  }
+
+  @Override
+  public int getDefaultTransactionIsolation()
+      throws SQLException {
+    return Connection.TRANSACTION_NONE;
+  }
+
+  @Override
+  public boolean dataDefinitionCausesTransactionCommit()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("dataDefinitionCausesTransactionCommit not supported");
+  }
+
+  @Override
+  public boolean dataDefinitionIgnoredInTransactions()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("dataDefinitionIgnoredInTransactions not supported");
+  }
+
+  @Override
+  public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("stored procedures not supported");
+  }
+
+  @Override
+  public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("stored procedures not supported");
+  }
+
+  /**
+   * Convert a pattern containing JDBC catalog search wildcards into
+   * Java regex patterns.
+   *
+   * @param pattern input which may contain '%' or '_' wildcard characters, or
+   * these characters escaped using {@link #getSearchStringEscape()}.
+   * @return replace %/_ with regex search characters, also handle escaped
+   * characters.
+   */
+  private String convertPattern(final String pattern) {
+    if (pattern == null) {
+      return ".*";
+    } else {
+      StringBuilder result = new StringBuilder(pattern.length());
+
+      boolean escaped = false;
+      for (int i = 0, len = pattern.length(); i < len; i++) {
+        char c = pattern.charAt(i);
+        if (escaped) {
+          if (c != SEARCH_STRING_ESCAPE) {
+            escaped = false;
+          }
+          result.append(c);
+        } else {
+          if (c == SEARCH_STRING_ESCAPE) {
+            escaped = true;
+            continue;
+          } else if (c == '%') {
+            result.append(".*");
+          } else if (c == '_') {
+            result.append('.');
+          } else {
+            result.append(Character.toLowerCase(c));
+          }
+        }
+      }
+
+      return result.toString();
+    }
+  }
+
+  @Override
+  public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types)
+      throws SQLException {
+    try {
+      final List<MetaDataTuple> resultTables = new ArrayList<MetaDataTuple>();
+      final String resultCatalog;
+      if (catalog == null) {
+        resultCatalog = "default";
+      } else {
+        resultCatalog = catalog;
+      }
+
+      String regtableNamePattern = convertPattern(tableNamePattern);
+      try {
+        TajoClient tajoClient = conn.getTajoClient();
+        List<String> tableNames = tajoClient.getTableList();
+        for (String eachTableName: tableNames) {
+          if (eachTableName.matches(regtableNamePattern)) {
+            MetaDataTuple tuple = new MetaDataTuple(5);
+
+            int index = 0;
+            tuple.put(index++, new TextDatum(resultCatalog));  //TABLE_CAT
+            tuple.put(index++, NullDatum.get());   //TABLE_SCHEM
+            tuple.put(index++, new TextDatum(eachTableName));
+            tuple.put(index++, new TextDatum("TABLE"));   //TABLE_TYPE
+            tuple.put(index++, NullDatum.get());   //REMARKS
+
+            resultTables.add(tuple);
+          }
+        }
+        Collections.sort(resultTables, new Comparator<MetaDataTuple> () {
+          @Override
+          public int compare(MetaDataTuple table1, MetaDataTuple table2) {
+            return table1.getString(2).compareTo(table2.getString(2));
+          }
+        });
+      } catch (Exception e) {
+        e.printStackTrace();
+        throw new SQLException(e);
+      }
+      TajoMetaDataResultSet result = new TajoMetaDataResultSet(
+          Arrays.asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "TABLE_TYPE", "REMARKS"),
+          Arrays.asList(Type.VARCHAR, Type.VARCHAR, Type.VARCHAR, Type.VARCHAR, Type.VARCHAR),
+          resultTables);
+
+      return result;
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new SQLException(e.getMessage(), e);
+    }
+  }
+
+  @Override
+  public ResultSet getSchemas()
+      throws SQLException {
+    return getSchemas(null, null);
+  }
+
+  @Override
+  public ResultSet getCatalogs()
+      throws SQLException {
+    List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
+    MetaDataTuple tuple = new MetaDataTuple(1);
+    tuple.put(0, new TextDatum("default"));
+    columns.add(tuple);
+
+    ResultSet result = new TajoMetaDataResultSet(
+        Arrays.asList("TABLE_CAT")
+        , Arrays.asList(Type.VARCHAR)
+        , columns);
+
+    return result;
+  }
+
+  @Override
+  public ResultSet getTableTypes()
+      throws SQLException {
+    List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
+    MetaDataTuple tuple = new MetaDataTuple(1);
+    tuple.put(0, new TextDatum("TABLE"));
+    columns.add(tuple);
+
+    ResultSet result = new TajoMetaDataResultSet(
+        Arrays.asList("TABLE_TYPE")
+        , Arrays.asList(Type.VARCHAR)
+        , columns);
+
+    return result;
+  }
+
+  @Override
+  public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types)
+      throws SQLException {
+    List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
+
+    return new TajoMetaDataResultSet(
+        Arrays.asList("TYPE_CAT", "TYPE_SCHEM", "TYPE_NAME", "CLASS_NAME", "DATA_TYPE"
+            , "REMARKS", "BASE_TYPE")
+        , Arrays.asList(Type.VARCHAR, Type.VARCHAR, Type.VARCHAR, Type.VARCHAR, Type.INT4, Type.VARCHAR, Type.INT4)
+        , columns);
+  }
+
+  @Override
+  public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
+      throws SQLException {
+    List<MetaDataTuple> columns = new ArrayList<MetaDataTuple>();
+    try {
+      if (catalog == null) {
+        catalog = "default";
+      }
+
+      String regtableNamePattern = convertPattern(tableNamePattern);
+      String regcolumnNamePattern = convertPattern(columnNamePattern);
+
+      List<String> tables = conn.getTajoClient().getTableList();
+      for (String table: tables) {
+        if (table.matches(regtableNamePattern)) {
+          TableDesc tableDesc = conn.getTajoClient().getTableDesc(table);
+          int pos = 0;
+          for (Column column: tableDesc.getSchema().getColumns()) {
+            if (column.getColumnName().matches(regcolumnNamePattern)) {
+              MetaDataTuple tuple = new MetaDataTuple(22);
+
+              int index = 0;
+              tuple.put(index++, new TextDatum(catalog));  //TABLE_CAT
+              tuple.put(index++, NullDatum.get());  //TABLE_SCHEM
+              tuple.put(index++, new TextDatum(table));  //TABLE_NAME
+              tuple.put(index++, new TextDatum(column.getColumnName()));  //COLUMN_NAME
+              // TODO - DATA_TYPE
+              tuple.put(index++, new TextDatum("" + ResultSetUtil.tajoTypeToSqlType(column.getDataType())));
+              tuple.put(index++, new TextDatum(ResultSetUtil.toSqlType(column.getDataType())));  //TYPE_NAME
+              tuple.put(index++, new TextDatum("0"));  //COLUMN_SIZE
+              tuple.put(index++, new TextDatum("0"));  //BUFFER_LENGTH
+              tuple.put(index++, new TextDatum("0"));  //DECIMAL_DIGITS
+              tuple.put(index++, new TextDatum("0"));  //NUM_PREC_RADIX
+              tuple.put(index++, new TextDatum("" + DatabaseMetaData.columnNullable));  //NULLABLE
+              tuple.put(index++, NullDatum.get());  //REMARKS
+              tuple.put(index++, NullDatum.get());  //COLUMN_DEF
+              tuple.put(index++, NullDatum.get());  //SQL_DATA_TYPE
+              tuple.put(index++, NullDatum.get());  //SQL_DATETIME_SUB
+              tuple.put(index++, new TextDatum("0"));  //CHAR_OCTET_LENGTH
+              tuple.put(index++, new TextDatum("" + pos));  //ORDINAL_POSITION
+              tuple.put(index++, new TextDatum("YES"));  //IS_NULLABLE
+              tuple.put(index++, NullDatum.get());  //SCOPE_CATLOG
+              tuple.put(index++, NullDatum.get());  //SCOPE_SCHEMA
+              tuple.put(index++, NullDatum.get());  //SCOPE_TABLE
+              tuple.put(index++, new TextDatum("0"));  //SOURCE_DATA_TYPE
+              columns.add(tuple);
+            }
+            pos++;
+          }
+        }
+      }
+
+      return new TajoMetaDataResultSet(
+          Arrays.asList("TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME", "DATA_TYPE"
+              , "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS", "NUM_PREC_RADIX"
+              , "NULLABLE", "REMARKS", "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB"
+              , "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE", "SCOPE_CATLOG", "SCOPE_SCHEMA"
+              , "SCOPE_TABLE", "SOURCE_DATA_TYPE")
+          , Arrays.asList(Type.VARCHAR, Type.VARCHAR, Type.VARCHAR, Type.VARCHAR, Type.INT4
+              , Type.VARCHAR, Type.INT4, Type.INT4, Type.INT4, Type.INT4
+              , Type.INT4, Type.VARCHAR, Type.VARCHAR, Type.INT4, Type.INT4
+              , Type.INT4, Type.INT4, Type.VARCHAR, Type.VARCHAR, Type.VARCHAR
+              , Type.VARCHAR, Type.INT4)
+          , columns);
+    } catch (Exception e) {
+      e.printStackTrace();
+      throw new SQLException(e);
+    }
+  }
+
+  @Override
+  public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("privileges not supported");
+  }
+
+  @Override
+  public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("privileges not supported");
+  }
+
+  @Override
+  public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("row identifiers not supported");
+  }
+
+  @Override
+  public ResultSet getVersionColumns(String catalog, String schema, String table)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("version columns not supported");
+  }
+
+  @Override
+  public ResultSet getPrimaryKeys(String catalog, String schema, String table)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("primary keys not supported");
+  }
+
+  @Override
+  public ResultSet getImportedKeys(String catalog, String schema, String table)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("imported keys not supported");
+  }
+
+  @Override
+  public ResultSet getExportedKeys(String catalog, String schema, String table)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("exported keys not supported");
+  }
+
+  @Override
+  public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("cross reference not supported");
+  }
+
+  @Override
+  public ResultSet getTypeInfo()
+      throws SQLException {
+    throw new UnsupportedOperationException("getTypeInfo not supported");
+  }
+
+  @Override
+  public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("indexes not supported");
+  }
+
+  @Override
+  public boolean deletesAreDetected(int type)
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean insertsAreDetected(int type)
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public Connection getConnection()
+      throws SQLException {
+    return conn;
+  }
+
+  @Override
+  public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("type hierarchies not supported");
+  }
+
+  @Override
+  public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("type hierarchies not supported");
+  }
+
+  @Override
+  public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("user-defined types not supported");
+  }
+
+  @Override
+  public int getResultSetHoldability()
+      throws SQLException {
+    return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+  }
+
+  @Override
+  public int getDatabaseMajorVersion()
+      throws SQLException {
+    return TajoDriver.MAJOR_VERSION;
+  }
+
+  @Override
+  public int getDatabaseMinorVersion()
+      throws SQLException {
+    return TajoDriver.MINOR_VERSION;
+  }
+
+  @Override
+  public int getJDBCMajorVersion()
+      throws SQLException {
+    return TajoDriver.JDBC_VERSION_MAJOR;
+  }
+
+  @Override
+  public int getJDBCMinorVersion()
+      throws SQLException {
+    return TajoDriver.JDBC_VERSION_MINOR;
+  }
+
+  @Override
+  public int getSQLStateType()
+      throws SQLException {
+    return DatabaseMetaData.sqlStateSQL;
+  }
+
+  @Override
+  public RowIdLifetime getRowIdLifetime()
+      throws SQLException {
+    return RowIdLifetime.ROWID_UNSUPPORTED;
+  }
+
+  @Override
+  public ResultSet getSchemas(String catalog, String schemaPattern)
+      throws SQLException {
+    return new TajoMetaDataResultSet(
+        Arrays.asList("TABLE_SCHEM", "TABLE_CATALOG"),
+        Arrays.asList(Type.VARCHAR, Type.VARCHAR),
+        null);
+  }
+
+  @Override
+  public boolean autoCommitFailureClosesAllResultSets()
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public ResultSet getClientInfoProperties()
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getClientInfoProperties not supported");
+  }
+
+  @Override
+  public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getFunctions not supported");
+  }
+
+  @Override
+  public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern)
+      throws SQLException {
+    throw new SQLFeatureNotSupportedException("getFunctionColumns not supported");
+  }
+
+  @Override
+  public boolean isCatalogAtStart() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean locatorsUpdateCopy() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean nullPlusNonNullIsNull() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean nullsAreSortedAtEnd() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean nullsAreSortedAtStart() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean nullsAreSortedHigh() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean nullsAreSortedLow() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean othersDeletesAreVisible(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean othersInsertsAreVisible(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean othersUpdatesAreVisible(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean ownDeletesAreVisible(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean ownInsertsAreVisible(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean ownUpdatesAreVisible(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean storesLowerCaseIdentifiers() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean storesMixedCaseIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean storesUpperCaseIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsANSI92EntryLevelSQL() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsANSI92FullSQL() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsANSI92IntermediateSQL() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsAlterTableWithAddColumn() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsAlterTableWithDropColumn() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsBatchUpdates() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCatalogsInDataManipulation() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCatalogsInProcedureCalls() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCatalogsInTableDefinitions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsColumnAliasing() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean supportsConvert() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsConvert(int fromType, int toType) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCoreSQLGrammar() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsCorrelatedSubqueries() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsDataDefinitionAndDataManipulationTransactions()
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsDataManipulationTransactionsOnly() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsDifferentTableCorrelationNames() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsExpressionsInOrderBy() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsExtendedSQLGrammar() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsFullOuterJoins() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsGetGeneratedKeys() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsGroupBy() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean supportsGroupByBeyondSelect() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsGroupByUnrelated() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsIntegrityEnhancementFacility() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsLikeEscapeClause() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsLimitedOuterJoins() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsMinimumSQLGrammar() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsMixedCaseIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsMultipleOpenResults() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsMultipleResultSets() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsMultipleTransactions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsNamedParameters() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsNonNullableColumns() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsOrderByUnrelated() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsOuterJoins() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsPositionedDelete() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsPositionedUpdate() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsResultSetConcurrency(int type, int concurrency)
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsResultSetHoldability(int holdability)
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsResultSetType(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSavepoints() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSchemasInDataManipulation() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSchemasInIndexDefinitions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSchemasInProcedureCalls() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSchemasInTableDefinitions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSelectForUpdate() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsStatementPooling() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsStoredProcedures() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSubqueriesInComparisons() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSubqueriesInExists() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSubqueriesInIns() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsSubqueriesInQuantifieds() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsTableCorrelationNames() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsTransactionIsolationLevel(int level)
+      throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsTransactions() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsUnion() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean supportsUnionAll() throws SQLException {
+    return true;
+  }
+
+  @Override
+  public boolean updatesAreDetected(int type) throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean usesLocalFilePerTable() throws SQLException {
+    return false;
+  }
+
+  @Override
+  public boolean usesLocalFiles() throws SQLException {
+    return false;
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public <T> T unwrap(Class<T> iface)
+      throws SQLException {
+    if (isWrapperFor(iface)) {
+      return (T) this;
+    }
+    throw new SQLFeatureNotSupportedException("No wrapper for " + iface);
+  }
+
+  @Override
+  public boolean isWrapperFor(Class<?> iface)
+      throws SQLException {
+    return iface.isInstance(this);
+  }
+
+  public boolean generatedKeyAlwaysReturned() throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("generatedKeyAlwaysReturned not supported");
+  }
+
+  public ResultSet getPseudoColumns(String catalog, String schemaPattern,
+                                    String tableNamePattern, String columnNamePattern) throws SQLException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("getPseudoColumns not supported");
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
new file mode 100644
index 0000000..03b45a6
--- /dev/null
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoDriver.java
@@ -0,0 +1,89 @@
+package org.apache.tajo.jdbc; /**
+ * 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.
+ */
+
+import org.apache.tajo.conf.TajoConf;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.sql.*;
+import java.util.Properties;
+import java.util.logging.Logger;
+
+public class TajoDriver implements Driver, Closeable {
+  public static final int MAJOR_VERSION = 1;
+  public static final int MINOR_VERSION = 0;
+
+  public static final int JDBC_VERSION_MAJOR = 4;
+  public static final int JDBC_VERSION_MINOR = 0;
+
+  public static final String TAJO_JDBC_URL_PREFIX = "jdbc:tajo://";
+
+  protected static TajoConf jdbcTajoConf;
+
+  static {
+    try {
+      DriverManager.registerDriver(new TajoDriver());
+    } catch (SQLException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+  }
+
+  public TajoDriver() {
+    jdbcTajoConf = new TajoConf();
+  }
+
+  @Override
+  public void close() throws IOException {
+  }
+
+  @Override
+  public Connection connect(String url, Properties properties) throws SQLException {
+    return new TajoConnection(url, properties);
+  }
+
+  @Override
+  public boolean acceptsURL(String url) throws SQLException {
+    return url.startsWith(TAJO_JDBC_URL_PREFIX);
+  }
+
+  @Override
+  public DriverPropertyInfo[] getPropertyInfo(String s, Properties properties) throws SQLException {
+    return new DriverPropertyInfo[0];
+  }
+
+  @Override
+  public int getMajorVersion() {
+    return MAJOR_VERSION;
+  }
+
+  @Override
+  public int getMinorVersion() {
+    return MINOR_VERSION;
+  }
+
+  @Override
+  public boolean jdbcCompliant() {
+    return false;
+  }
+
+  public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+    // JDK 1.7
+    throw new SQLFeatureNotSupportedException("getParentLogger not supported");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tajo/blob/b6a5ff0c/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoMetaDataResultSet.java
----------------------------------------------------------------------
diff --git a/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoMetaDataResultSet.java b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoMetaDataResultSet.java
new file mode 100644
index 0000000..fb0a834
--- /dev/null
+++ b/tajo-jdbc/src/main/java/org/apache/tajo/jdbc/TajoMetaDataResultSet.java
@@ -0,0 +1,75 @@
+package org.apache.tajo.jdbc; /**
+ * 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.
+ */
+
+import org.apache.tajo.catalog.Schema;
+import org.apache.tajo.common.TajoDataTypes.Type;
+import org.apache.tajo.datum.Datum;
+import org.apache.tajo.storage.Tuple;
+
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.List;
+
+public class TajoMetaDataResultSet extends TajoResultSetBase {
+  private List<MetaDataTuple> values;
+
+  public TajoMetaDataResultSet(List<String> columns, List<Type> types, List<MetaDataTuple> values) {
+    init();
+    schema = new Schema();
+
+    int index = 0;
+    if(columns != null) {
+      for(String columnName: columns) {
+        schema.addColumn(columnName, types.get(index++));
+      }
+    }
+    this.values = values;
+    totalRow = values == null ? 0 : values.size();
+  }
+
+  @Override
+  protected Tuple nextTuple() throws IOException {
+    if(curRow >= totalRow) {
+      return null;
+    }
+    return values.get(curRow);
+  }
+
+  @Override
+  public void close() throws SQLException {
+  }
+
+  @Override
+  public String getString(int fieldId) throws SQLException {
+    Datum datum = cur.get(fieldId - 1);
+    if(datum == null) {
+      return null;
+    }
+
+    return datum.asChars();
+  }
+
+  @Override
+  public String getString(String name) throws SQLException {
+    Datum datum = cur.get(findColumn(name));
+    if(datum == null) {
+      return null;
+    }
+    return datum.asChars();
+  }
+}