diff --git a/src/console/CMakeLists.txt b/src/console/CMakeLists.txt
index 93e24feb06a92c868af03e79f27db80487eb29ae..04831c89422105b1fed502b52679e8d48b1e00da 100644
--- a/src/console/CMakeLists.txt
+++ b/src/console/CMakeLists.txt
@@ -6,7 +6,6 @@ add_executable(
     GraphDbConsole.cpp
     $<TARGET_OBJECTS:console_obj>
     $<TARGET_OBJECTS:client_cpp_obj>
-    $<TARGET_OBJECTS:dataman_obj>
     $<TARGET_OBJECTS:base_obj>
     $<TARGET_OBJECTS:vgraph_thrift_obj>
     $<TARGET_OBJECTS:time_obj>
diff --git a/src/console/CliManager.cpp b/src/console/CliManager.cpp
index f4f8848c5f2d30412d39757e0871eae7cc771a36..c03a0097ae4e07b3c379215d6d058eef2b0bd5da 100644
--- a/src/console/CliManager.cpp
+++ b/src/console/CliManager.cpp
@@ -64,14 +64,14 @@ bool CliManager::connect(const std::string& addr,
     username_ = user;
 
     auto client = std::make_unique<GraphDbClient>(addr_, port_);
-    int32_t err = client->connect(user, pass);
-    if (!err) {
+    cpp2::ErrorCode res = client->connect(user, pass);
+    if (res == cpp2::ErrorCode::SUCCEEDED) {
         std::cerr << "\nWelcome to vGraph (Version 0.1)\n\n";
         cmdProcessor_ = std::make_unique<CmdProcessor>(std::move(client));
         return true;
     } else {
         // There is an error
-        std::cout << "Authentication failed: " << client->getErrorStr() << "\n";
+        std::cout << "Authentication failed\n";
         return false;
     }
 }
diff --git a/src/console/CmdProcessor.cpp b/src/console/CmdProcessor.cpp
index 46d911ad3e07982e96abeacfed1a75055228a295..a4ef04215abccbc30765fd75445cf03b9565435c 100644
--- a/src/console/CmdProcessor.cpp
+++ b/src/console/CmdProcessor.cpp
@@ -7,89 +7,189 @@
 #include "base/Base.h"
 #include "console/CmdProcessor.h"
 #include "time/Duration.h"
-#include "dataman/RowSetReader.h"
-#include "dataman/RowReader.h"
 
 namespace vesoft {
 namespace vgraph {
 
 #define GET_VALUE_WIDTH(VT, FN, FMT) \
-    VT val; \
-    if (fieldIt->get ## FN (val) == ResultType::SUCCEEDED) { \
-        int32_t len = folly::stringPrintf(FMT, val).size(); \
-        if (widths[fieldIdx] < len) { \
-            widths[fieldIdx] = len; \
-        } \
+    VT val = col.get_ ## FN(); \
+    size_t len = folly::stringPrintf(FMT, val).size(); \
+    if (widths[idx] < len) { \
+        widths[idx] = len; \
+        genFmt = true; \
     }
 
-std::vector<int16_t> CmdProcessor::calColumnWidths(
-        const RowSetReader* dataReader) const {
-    std::vector<int16_t> widths;
+void CmdProcessor::calColumnWidths(
+        const cpp2::ExecutionResponse& resp,
+        std::vector<size_t>& widths,
+        std::vector<std::string>& formats) const {
+    widths.clear();
+    formats.clear();
 
     // Check column names first
-    auto* schema = dataReader->schema();
-    for (int i = 0; i < schema->getNumFields(0); i++) {
-        widths.emplace_back(strlen(schema->getFieldName(i, 0)));
+    if (resp.get_column_names() != nullptr) {
+        for (size_t i = 0; i < resp.get_column_names()->size(); i++) {
+            widths.emplace_back(resp.get_column_names()->at(i).size());
+        }
+    }
+    if (widths.size() == 0) {
+        return;
     }
 
-    // TODO Then check data width
-    auto rowIt = dataReader->begin();
-    while (bool(rowIt)) {
-        int32_t fieldIdx = 0;
-        auto fieldIt = rowIt->begin();
-        while (bool(fieldIt)) {
-            switch (schema->getFieldType(fieldIdx, 0)->get_type()) {
-                case cpp2::SupportedType::BOOL: {
+    std::vector<cpp2::ColumnValue::Type> types(
+        widths.size(), cpp2::ColumnValue::Type::__EMPTY__);
+    formats.resize(widths.size());
+    // Then check data width
+    for (auto& row : *(resp.get_rows())) {
+        size_t idx = 0;
+        for (auto& col : row.get_columns()) {
+            CHECK(types[idx] == cpp2::ColumnValue::Type::__EMPTY__
+                  || types[idx] == col.getType());
+            bool genFmt = types[idx] == cpp2::ColumnValue::Type::__EMPTY__;
+            if (types[idx] == cpp2::ColumnValue::Type::__EMPTY__) {
+                types[idx] = col.getType();
+            } else {
+                CHECK_EQ(types[idx], col.getType());
+            }
+
+            switch (col.getType()) {
+                case cpp2::ColumnValue::Type::__EMPTY__: {
+                    break;
+                }
+                case cpp2::ColumnValue::Type::boolean: {
                     // Enough to hold "false"
-                    if (widths[fieldIdx] < 5) {
-                        widths[fieldIdx] = 5;
+                    if (widths[idx] < 5UL) {
+                        widths[idx] = 5UL;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%lds |", widths[idx]);
                     }
                     break;
                 }
-                case cpp2::SupportedType::INT: {
-                    GET_VALUE_WIDTH(int64_t, Int, "%ld")
+                case cpp2::ColumnValue::Type::integer: {
+                    GET_VALUE_WIDTH(int64_t, integer, "%ld")
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldld |", widths[idx]);
+                    }
                     break;
                 }
-                case cpp2::SupportedType::FLOAT: {
-                    GET_VALUE_WIDTH(float, Float, "%f")
+                case cpp2::ColumnValue::Type::id: {
+                    // Enough to hold "0x{16 letters}"
+                    if (widths[idx] < 18UL) {
+                        widths[idx] = 18UL;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldX |", widths[idx]);
+                    }
                     break;
                 }
-                case cpp2::SupportedType::DOUBLE: {
-                    GET_VALUE_WIDTH(double, Double, "%lf")
+                case cpp2::ColumnValue::Type::single_precision: {
+                    GET_VALUE_WIDTH(float, single_precision, "%f")
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldf |", widths[idx]);
+                    }
                     break;
                 }
-                case cpp2::SupportedType::STRING: {
-                    folly::StringPiece val;
-                    if (fieldIt->getString(val) == ResultType::SUCCEEDED) {
-                        if (widths[fieldIdx] < static_cast<int64_t>(val.size())) {
-                            widths[fieldIdx] = val.size();
-                        }
+                case cpp2::ColumnValue::Type::double_precision: {
+                    GET_VALUE_WIDTH(double, double_precision, "%lf")
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldf |", widths[idx]);
                     }
                     break;
                 }
-                case cpp2::SupportedType::VID: {
-                    // Enough to hold "0x{16 letters}"
-                    if (widths[fieldIdx] < 18) {
-                        widths[fieldIdx] = 18;
+                case cpp2::ColumnValue::Type::str: {
+                    size_t len = col.get_str().size();
+                    if (widths[idx] < len) {
+                        widths[idx] = len;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%lds |", widths[idx]);
+                    }
+                    break;
+                }
+                case cpp2::ColumnValue::Type::timestamp: {
+                    GET_VALUE_WIDTH(int64_t, timestamp, "%ld")
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldld |", widths[idx]);
+                    }
+                    break;
+                }
+                case cpp2::ColumnValue::Type::year: {
+                    if (widths[idx] < 4UL) {
+                        widths[idx] = 4UL;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] = folly::stringPrintf(" %%%ldd |", widths[idx]);
+                    }
+                    break;
+                }
+                case cpp2::ColumnValue::Type::month: {
+                    if (widths[idx] < 7UL) {
+                        widths[idx] = 7UL;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] = folly::stringPrintf(" %%%ldd/%%02d |",
+                                                           widths[idx] - 3);
+                    }
+                    break;
+                }
+                case cpp2::ColumnValue::Type::date: {
+                    if (widths[idx] < 10UL) {
+                        widths[idx] = 10UL;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldd/%%02d/%%02d |",
+                                                widths[idx] - 6);
                     }
                     break;
                 }
-                default: {
+                case cpp2::ColumnValue::Type::datetime: {
+                    if (widths[idx] < 26UL) {
+                        widths[idx] = 26UL;
+                        genFmt = true;
+                    }
+                    if (genFmt) {
+                        formats[idx] =
+                            folly::stringPrintf(" %%%ldd/%%02d/%%02d"
+                                                " %%02d:%%02d:%%02d"
+                                                ".%%03d%%03d |",
+                                                widths[idx] - 22);
+                    }
+                    break;
                 }
             }
-            ++fieldIt;
-            ++fieldIdx;
+            ++idx;
         }
-        ++rowIt;
     }
-
-    return std::move(widths);
 }
 #undef GET_VALUE_WIDTH
 
 
-int32_t CmdProcessor::printResult(const RowSetReader* dataReader) const {
-    std::vector<int16_t> widths = calColumnWidths(dataReader);
+void CmdProcessor::printResult(const cpp2::ExecutionResponse& resp) const {
+    std::vector<size_t> widths;
+    std::vector<std::string> formats;
+
+    calColumnWidths(resp, widths, formats);
+
+    if (widths.size() == 0) {
+        return;
+    }
+
+    // Calculate the total width
     int32_t sum = 0;
     for (auto w : widths) {
         sum += w;
@@ -99,117 +199,109 @@ int32_t CmdProcessor::printResult(const RowSetReader* dataReader) const {
     std::string rowLine(sum + 3 * widths.size() + 1, '-');
     std::cout << headerLine << "\n|";
 
-    std::vector<std::string> formats = printHeader(dataReader, widths);
+    printHeader(resp, widths);
     std::cout << headerLine << "\n";
 
-    int32_t numRows = printData(dataReader, rowLine, formats);
-    return numRows;
+    printData(resp, rowLine, widths, formats);
 }
 
 
-std::vector<std::string> CmdProcessor::printHeader(
-        const RowSetReader* dataReader,
-        const std::vector<int16_t>& widths) const {
-    std::vector<std::string> formats;
+void CmdProcessor::printHeader(
+        const cpp2::ExecutionResponse& resp,
+        const std::vector<size_t>& widths) const {
+    size_t idx = 0;
+    if (resp.get_column_names() == nullptr) {
+        return;
+    }
 
-    auto* schema = dataReader->schema();
-    for (int i = 0; i < schema->getNumFields(0); i++) {
-        std::string fmt = folly::stringPrintf(" %%%ds |", widths[i]);
-        std::cout << folly::stringPrintf(fmt.c_str(), schema->getFieldName(i, 0));
-        switch (schema->getFieldType(i, 0)->get_type()) {
-            case cpp2::SupportedType::BOOL: {
-                formats.emplace_back(folly::stringPrintf(" %%%ds |", widths[i]));
-                break;
-            }
-            case cpp2::SupportedType::INT: {
-                formats.emplace_back(folly::stringPrintf(" %%%dld |", widths[i]));
-                break;
-            }
-            case cpp2::SupportedType::FLOAT: {
-                formats.emplace_back(folly::stringPrintf(" %%%df |", widths[i]));
-                break;
-            }
-            case cpp2::SupportedType::DOUBLE: {
-                formats.emplace_back(folly::stringPrintf(" %%%df |", widths[i]));
-                break;
-            }
-            case cpp2::SupportedType::STRING: {
-                formats.emplace_back(folly::stringPrintf(" %%%ds |", widths[i]));
-                break;
-            }
-            case cpp2::SupportedType::VID: {
-                formats.emplace_back(folly::stringPrintf(" %%%dX |", widths[i]));
-                break;
-            }
-            default: {
-                formats.emplace_back(" *ERROR* |");
-            }
-        }
+    for (auto& cname : (*resp.get_column_names())) {
+        std::string fmt = folly::stringPrintf(" %%%lds |", widths[idx]);
+        std::cout << folly::stringPrintf(fmt.c_str(), cname.c_str());
     }
     std::cout << "\n";
-
-    return std::move(formats);
 }
 
 
-#define PRINT_FIELD_VALUE(VT, FN, VAL) \
-    VT val; \
-    if (fIt->get ## FN (val) == ResultType::SUCCEEDED) { \
-        std::cout << folly::stringPrintf(formats[fIdx].c_str(), (VAL)); \
-    } else { \
-        std::cout << " *BAD* |"; \
-    }
+#define PRINT_FIELD_VALUE(...) \
+    std::cout << folly::stringPrintf(formats[cIdx].c_str(), __VA_ARGS__)
 
-int32_t CmdProcessor::printData(const RowSetReader* dataReader,
-                                const std::string& rowLine,
-                                const std::vector<std::string>& formats) const {
-    int32_t numRows = 0;
+void CmdProcessor::printData(const cpp2::ExecutionResponse& resp,
+                             const std::string& rowLine,
+                             const std::vector<size_t>& widths,
+                             const std::vector<std::string>& formats) const {
+    if (resp.get_rows() == nullptr) {
+        return;
+    }
 
-    auto* schema = dataReader->schema();
-    auto rowIt = dataReader->begin();
-    while (bool(rowIt)) {
-        int32_t fIdx = 0;
-        auto fIt = rowIt->begin();
+    for (auto& row : (*resp.get_rows())) {
+        int32_t cIdx = 0;
         std::cout << "|";
-        while (bool(fIt)) {
-            switch (schema->getFieldType(fIdx, 0)->get_type()) {
-                case cpp2::SupportedType::BOOL: {
-                    PRINT_FIELD_VALUE(bool, Bool, (val ? "true" : "false"))
+        for (auto& col : row.get_columns()) {
+            switch (col.getType()) {
+                case cpp2::ColumnValue::Type::__EMPTY__: {
+                    std::string fmt = folly::stringPrintf(" %%%ldc |", widths[cIdx]);
+                    std::cout << folly::stringPrintf(fmt.c_str(), ' ');
+                    break;
+                }
+                case cpp2::ColumnValue::Type::boolean: {
+                    PRINT_FIELD_VALUE(col.get_boolean() ? "true" : "false");
+                    break;
+                }
+                case cpp2::ColumnValue::Type::integer: {
+                    PRINT_FIELD_VALUE(col.get_integer());
                     break;
                 }
-                case cpp2::SupportedType::INT: {
-                    PRINT_FIELD_VALUE(int64_t, Int, val)
+                case cpp2::ColumnValue::Type::id: {
+                    PRINT_FIELD_VALUE(col.get_id());
                     break;
                 }
-                case cpp2::SupportedType::FLOAT: {
-                    PRINT_FIELD_VALUE(float, Float, val)
+                case cpp2::ColumnValue::Type::single_precision: {
+                    PRINT_FIELD_VALUE(col.get_single_precision());
                     break;
                 }
-                case cpp2::SupportedType::DOUBLE: {
-                    PRINT_FIELD_VALUE(double, Double, val)
+                case cpp2::ColumnValue::Type::double_precision: {
+                    PRINT_FIELD_VALUE(col.get_double_precision());
                     break;
                 }
-                case cpp2::SupportedType::STRING: {
-                    PRINT_FIELD_VALUE(folly::StringPiece, String, val.toString().c_str())
+                case cpp2::ColumnValue::Type::str: {
+                    PRINT_FIELD_VALUE(col.get_str().c_str());
                     break;
                 }
-                case cpp2::SupportedType::VID: {
-                    PRINT_FIELD_VALUE(int64_t, Vid, val)
+                case cpp2::ColumnValue::Type::timestamp: {
+                    PRINT_FIELD_VALUE(col.get_timestamp());
                     break;
                 }
-                default: {
-                    std::cout << " *ERROR* |";
+                case cpp2::ColumnValue::Type::year: {
+                    PRINT_FIELD_VALUE(col.get_year());
+                    break;
+                }
+                case cpp2::ColumnValue::Type::month: {
+                    cpp2::YearMonth month = col.get_month();
+                    PRINT_FIELD_VALUE(month.get_year(), month.get_month());
+                    break;
+                }
+                case cpp2::ColumnValue::Type::date: {
+                    cpp2::Date date = col.get_date();
+                    PRINT_FIELD_VALUE(date.get_year(), date.get_month(), date.get_day());
+                    break;
+                }
+                case cpp2::ColumnValue::Type::datetime: {
+                    cpp2::DateTime dt = col.get_datetime();
+                    PRINT_FIELD_VALUE(dt.get_year(),
+                                      dt.get_month(),
+                                      dt.get_day(),
+                                      dt.get_hour(),
+                                      dt.get_minute(),
+                                      dt.get_second(),
+                                      dt.get_millisec(),
+                                      dt.get_microsec());
+                    break;
                 }
             }
-            ++fIt;
-            ++fIdx;
+            ++cIdx;
         }
         std::cout << "\n" << rowLine << "\n";
-        ++numRows;
-        ++rowIt;
     }
-
-    return numRows;
 }
 #undef PRINT_FIELD_VALUE
 
@@ -231,23 +323,27 @@ bool CmdProcessor::processClientCmd(folly::StringPiece cmd,
 
 void CmdProcessor::processServerCmd(folly::StringPiece cmd) {
     time::Duration dur;
-    std::unique_ptr<RowSetReader> dataReader;
-    int32_t res = client_->execute(cmd, dataReader);
-    if (!res) {
+    cpp2::ExecutionResponse resp;
+    cpp2::ErrorCode res = client_->execute(cmd, resp);
+    if (res == cpp2::ErrorCode::SUCCEEDED) {
         // Succeeded
-        auto* schema = dataReader->schema();
-        UNUSED(schema);
-        int32_t numRows = 0;
-        if (dataReader->schema()) {
-            // Only print when the schema is no empty
-            numRows = printResult(dataReader.get());
+        printResult(resp);
+        if (resp.get_rows() != nullptr) {
+            std::cout << "Got " << resp.get_rows()->size()
+                      << " rows (Time spent: "
+                      << resp.get_latency_in_ms() << "/"
+                      << dur.elapsedInMSec() << " ms)\n";
+        } else {
+            std::cout << "Execution succeeded (Time spent: "
+                      << resp.get_latency_in_ms() << "/"
+                      << dur.elapsedInMSec() << " ms)\n";
         }
-        std::cout << "Got " << numRows << " rows (Time spent: "
-                  << client_->getServerLatency() << "/"
-                  << dur.elapsedInMSec() << " ms)\n";
     } else {
-        std::cout << "[ERROR (" << res << ")]  "
-                  << client_->getErrorStr() << "\n";
+        // TODO(sye) Need to print human-readable error strings
+        auto msg = resp.get_error_msg();
+        std::cout << "[ERROR (" << static_cast<int32_t>(res)
+                  << ")]: " << (msg != nullptr ? *msg : "")
+                  << "\n";
     }
 }
 
diff --git a/src/console/CmdProcessor.h b/src/console/CmdProcessor.h
index 88b5a1be8ed1af1fb461d30512d523837fb5752a..8de95f7c96bc9e3af1da0fc02c3112789d92b2e4 100644
--- a/src/console/CmdProcessor.h
+++ b/src/console/CmdProcessor.h
@@ -34,15 +34,17 @@ private:
 
     void processServerCmd(folly::StringPiece cmd);
 
-    std::vector<int16_t> calColumnWidths(const RowSetReader* dataReader) const;
-
-    int32_t printResult(const RowSetReader* dataReader) const;
-    std::vector<std::string> printHeader(const RowSetReader* dataReader,
-                                         const std::vector<int16_t>& widths) const;
-    // The method returns the total number of rows
-    int32_t printData(const RowSetReader* dataReader,
-                      const std::string& rowLine,
-                      const std::vector<std::string>& formats) const;
+    void calColumnWidths(const cpp2::ExecutionResponse& resp,
+                         std::vector<size_t>& widths,
+                         std::vector<std::string>& formats) const;
+
+    void printResult(const cpp2::ExecutionResponse& resp) const;
+    void printHeader(const cpp2::ExecutionResponse& resp,
+                     const std::vector<size_t>& widths) const;
+    void printData(const cpp2::ExecutionResponse& resp,
+                   const std::string& rowLine,
+                   const std::vector<size_t>& widths,
+                   const std::vector<std::string>& formats) const;
 };
 
 }  // namespace vgraph