This is an automated email from the ASF dual-hosted git repository.

jiangtian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iotdb.git


The following commit(s) were added to refs/heads/master by this push:
     new a1a972c8462 feat(client-cpp): add basic TableModel settings & 
insertRelationalTablet interface (#14097)
a1a972c8462 is described below

commit a1a972c8462dddf11abb79928f4cd47c19ad30e4
Author: xiangmy21 <[email protected]>
AuthorDate: Wed Dec 4 09:53:29 2024 +0800

    feat(client-cpp): add basic TableModel settings & insertRelationalTablet 
interface (#14097)
    
    * feat(client-cpp): add sqlDialect, database, insertRelationalTablet(not 
tested).
    
    * temporary
    
    * feat: add test for client-cpp insertRelationalTablet
    
    * fix cmakes in linux
    
    * fix: test files
    
    * fix: multiline strings
    
    * fix: unique_ptr
    
    * fix: test success.
    
    * chore: add SessionTableModelExample.cpp
    
    * fix(client-cpp): add dataType "TIMESTAMP" parsing
    
    * refact(client-cpp): extract TableModelSession
    
    * fix(client-cpp): fix syntax errors.
    
    * fix(client-cpp): fix many syntax errors.
    
    * fix(client-cpp): test reopen link
    
    * fix(client-cpp): ParameterType need to be same with DataType
    
    * fix(client-cpp): type conversion in pointer.
    
    * fix(client-cpp): fix pointer syntax error.
    
    * fix(client-cpp): adjust datatype categories.
---
 .../src/AlignedTimeseriesSessionExample.cpp        |  30 +--
 example/client-cpp-example/src/SessionExample.cpp  |  20 +-
 .../src/TableModelSessionExample.cpp               | 212 +++++++++++++++++++++
 iotdb-client/client-cpp/pom.xml                    |  16 ++
 .../client-cpp/src/main/AbstractSessionBuilder.h   |  37 ++++
 iotdb-client/client-cpp/src/main/Session.cpp       | 110 ++++++-----
 iotdb-client/client-cpp/src/main/Session.h         | 173 ++++++++++++++++-
 iotdb-client/client-cpp/src/main/TableSession.cpp  |  44 +++++
 iotdb-client/client-cpp/src/main/TableSession.h    |  43 +++++
 .../client-cpp/src/main/TableSessionBuilder.h      |  76 ++++++++
 iotdb-client/client-cpp/src/test/CMakeLists.txt    |   9 +
 iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp |   2 +-
 .../src/test/cpp/sessionRelationalIT.cpp           | 117 ++++++++++++
 .../client-cpp/src/test/main_Relational.cpp        |  42 ++++
 14 files changed, 843 insertions(+), 88 deletions(-)

diff --git a/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp 
b/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp
index 8f175cb7650..2cc04ab3b39 100644
--- a/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp
+++ b/example/client-cpp-example/src/AlignedTimeseriesSessionExample.cpp
@@ -168,9 +168,9 @@ void insertAlignedTablet() {
         int randVal1 = 123456;
         double randVal2 = 123456.1234;
         double randVal3 = 123456.1234;
-        tablet.addValue(0, row, &randVal1);
-        tablet.addValue(1, row, &randVal2);
-        tablet.addValue(2, row, &randVal3);
+        tablet.addValue(0, row, randVal1);
+        tablet.addValue(1, row, randVal2);
+        tablet.addValue(2, row, randVal3);
         if (tablet.rowSize == tablet.maxRowNumber) {
             session->insertTablet(tablet, true);
             tablet.reset();
@@ -212,23 +212,23 @@ void insertAlignedTablets() {
         int randVal11 = rand();
         int randVal12 = rand();
         int randVal13 = rand();
-        tablet1.addValue(0, row1, &randVal11);
-        tablet2.addValue(0, row2, &randVal12);
-        tablet3.addValue(0, row3, &randVal13);
+        tablet1.addValue(0, row1, randVal11);
+        tablet2.addValue(0, row2, randVal12);
+        tablet3.addValue(0, row3, randVal13);
 
         double randVal21 = rand() / 99.9;
         double randVal22 = rand() / 99.9;
         double randVal23 = rand() / 99.9;
-        tablet1.addValue(1, row1, &randVal21);
-        tablet2.addValue(1, row2, &randVal22);
-        tablet3.addValue(1, row3, &randVal23);
+        tablet1.addValue(1, row1, randVal21);
+        tablet2.addValue(1, row2, randVal22);
+        tablet3.addValue(1, row3, randVal23);
 
         bool randVal31 = (bool)(rand() % 2);
         bool randVal32 = (bool)(rand() % 2);
         bool randVal33 = (bool)(rand() % 2);
-        tablet1.addValue(2, row1, &randVal31);
-        tablet2.addValue(2, row2, &randVal32);
-        tablet3.addValue(2, row3, &randVal33);
+        tablet1.addValue(2, row1, randVal31);
+        tablet2.addValue(2, row2, randVal32);
+        tablet3.addValue(2, row3, randVal33);
 
         if (tablet1.rowSize == tablet1.maxRowNumber) {
             session->insertAlignedTablets(tabletMap, true);
@@ -267,11 +267,11 @@ void insertNullableTabletWithAlignedTimeseries() {
             int64_t randVal2 = rand();
             bool randVal3 = (bool)(rand() % 2);
             if (i == 0) {
-                tablet.addValue(i, row, &randVal1);
+                tablet.addValue(i, row, randVal1);
             } else if (i == 1) {
-                tablet.addValue(i, row, &randVal2);
+                tablet.addValue(i, row, randVal2);
             } else {
-                tablet.addValue(i, row, &randVal3);
+                tablet.addValue(i, row, randVal3);
             }
             // mark null value
             if ((row % 3) == (unsigned int) i) {
diff --git a/example/client-cpp-example/src/SessionExample.cpp 
b/example/client-cpp-example/src/SessionExample.cpp
index c3f5602cb08..2803d18976c 100644
--- a/example/client-cpp-example/src/SessionExample.cpp
+++ b/example/client-cpp-example/src/SessionExample.cpp
@@ -159,13 +159,13 @@ void insertTablet() {
         tablet.timestamps[row] = time;
 
         bool randVal1 = rand() % 2;
-        tablet.addValue(0, row, &randVal1);
+        tablet.addValue(0, row, randVal1);
 
         int randVal2 = rand();
-        tablet.addValue(1, row, &randVal2);
+        tablet.addValue(1, row, randVal2);
 
         float randVal3 = (float)(rand() / 99.9);
-        tablet.addValue(2, row, &randVal3);
+        tablet.addValue(2, row, randVal3);
 
         if (tablet.rowSize == tablet.maxRowNumber) {
             session->insertTablet(tablet, true);
@@ -236,22 +236,22 @@ void insertTablets() {
         tablet2.timestamps[row2] = time;
 
         int64_t randVal11 = rand();
-        tablet1.addValue(0, row1, &randVal11);
+        tablet1.addValue(0, row1, randVal11);
 
         double randVal12 = rand() / 99.9;
-        tablet1.addValue(1, row1, &randVal12);
+        tablet1.addValue(1, row1, randVal12);
 
         string randVal13 = "string" + to_string(rand());
-        tablet1.addValue(2, row1, &randVal13);
+        tablet1.addValue(2, row1, randVal13);
 
         int64_t randVal21 = rand();
-        tablet2.addValue(0, row2, &randVal21);
+        tablet2.addValue(0, row2, randVal21);
 
         double randVal22 = rand() / 99.9;
-        tablet2.addValue(1, row2, &randVal22);
+        tablet2.addValue(1, row2, randVal22);
 
         string randVal23 = "string" + to_string(rand());
-        tablet2.addValue(2, row2, &randVal23);
+        tablet2.addValue(2, row2, randVal23);
 
         if (tablet1.rowSize == tablet1.maxRowNumber) {
             session->insertTablets(tabletMap, true);
@@ -292,7 +292,7 @@ void insertTabletWithNullValues() {
         tablet.timestamps[row] = time;
         for (int i = 0; i < 3; i++) {
             int64_t randVal = rand();
-            tablet.addValue(i, row, &randVal);
+            tablet.addValue(i, row, randVal);
             // mark null value
             if (row % 3 == (unsigned int) i) {
                 tablet.bitMaps[i].mark(row);
diff --git a/example/client-cpp-example/src/TableModelSessionExample.cpp 
b/example/client-cpp-example/src/TableModelSessionExample.cpp
new file mode 100644
index 00000000000..276dfe99df1
--- /dev/null
+++ b/example/client-cpp-example/src/TableModelSessionExample.cpp
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "TableSession.h"
+#include "TableSessionBuilder.h"
+
+using namespace std;
+
+TableSession *session;
+
+void insertRelationalTablet() {
+
+    vector<pair<string, TSDataType::TSDataType>> schemaList {
+        make_pair("region_id", TSDataType::TEXT),
+        make_pair("plant_id", TSDataType::TEXT),
+        make_pair("device_id", TSDataType::TEXT),
+        make_pair("model", TSDataType::TEXT),
+        make_pair("temperature", TSDataType::FLOAT),
+        make_pair("humidity", TSDataType::DOUBLE)
+    };
+
+    vector<ColumnCategory> columnTypes = {
+        ColumnCategory::ID,
+        ColumnCategory::ID,
+        ColumnCategory::ID,
+        ColumnCategory::ATTRIBUTE,
+        ColumnCategory::MEASUREMENT,
+        ColumnCategory::MEASUREMENT
+    };
+
+    Tablet tablet("table1", schemaList, columnTypes, 100);
+
+    for (int row = 0; row < 100; row++) {
+        int rowIndex = tablet.rowSize++;
+        tablet.timestamps[rowIndex] = row;
+        tablet.addValue("region_id", rowIndex, "1");
+        tablet.addValue("plant_id", rowIndex, "5");
+        tablet.addValue("device_id", rowIndex, "3");
+        tablet.addValue("model", rowIndex, "A");
+        tablet.addValue("temperature", rowIndex, 37.6F);
+        tablet.addValue("humidity", rowIndex, 111.1);
+        if (tablet.rowSize == tablet.maxRowNumber) {
+            session->insert(tablet);
+            tablet.reset();
+        }
+    }
+
+    if (tablet.rowSize != 0) {
+        session->insert(tablet);
+        tablet.reset();
+    }
+}
+
+template<typename T>
+inline void Output(vector<T> &columnNames) {
+    for (auto &name: columnNames) {
+        cout << name << "\t";
+    }
+    cout << endl;
+}
+
+int main() {
+    try {
+        session = new TableSessionBuilder()
+            .host("127.0.0.1")
+            .rpcPort(6667)
+            .username("root")
+            .password("root")
+            .build();
+
+        cout << "Create Database db1,db2" << endl;
+        try {
+            session->executeNonQueryStatement("CREATE DATABASE IF NOT EXISTS 
db1");
+            session->executeNonQueryStatement("CREATE DATABASE IF NOT EXISTS 
db2");
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Use db1 as database" << endl;
+        try {
+            session->executeNonQueryStatement("USE db1");
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Create Table table1,table2" << endl;
+        try {
+            session->executeNonQueryStatement("create table 
db1.table1(region_id STRING ID, plant_id STRING ID, device_id STRING ID, model 
STRING ATTRIBUTE, temperature FLOAT MEASUREMENT, humidity DOUBLE MEASUREMENT) 
with (TTL=3600000)");
+            session->executeNonQueryStatement("create table 
db2.table2(region_id STRING ID, plant_id STRING ID, color STRING ATTRIBUTE, 
temperature FLOAT MEASUREMENT, speed DOUBLE MEASUREMENT) with (TTL=6600000)");
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Show Tables" << endl;
+        try {
+            SessionDataSet dataSet = session->executeQueryStatement("SHOW 
TABLES");
+            Output(dataSet.getColumnNames());
+            while(dataSet.hasNext()) {
+                Output(dataSet.next());
+            }
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Show tables from specific database" << endl;
+        try {
+            SessionDataSet dataSet = session->executeQueryStatement("SHOW 
TABLES FROM db1");
+            Output(dataSet.getColumnNames());
+            while(dataSet.hasNext()) {
+                Output(dataSet.next());
+            }
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "InsertTablet" << endl;
+        try {
+            insertRelationalTablet();
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Query Table Data" << endl;
+        try {
+            SessionDataSet dataSet = session->executeQueryStatement("SELECT * 
FROM table1"
+                " where region_id = '1' and plant_id in ('3', '5') and 
device_id = '3'");
+            Output(dataSet.getColumnNames());
+            Output(dataSet.getColumnTypeList());
+            while(dataSet.hasNext()) {
+                Output(dataSet.next());
+            }
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        session->close();
+
+        // specify database in constructor
+        session = new TableSessionBuilder()
+            .host("127.0.0.1")
+            .rpcPort(6667)
+            .username("root")
+            .password("root")
+            .database("db1")
+            .build();
+
+        cout << "Show tables from current database(db1)" << endl;
+        try {
+            SessionDataSet dataSet = session->executeQueryStatement("SHOW 
TABLES");
+            Output(dataSet.getColumnNames());
+            while(dataSet.hasNext()) {
+                Output(dataSet.next());
+            }
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Change database to db2" << endl;
+        try {
+            session->executeNonQueryStatement("USE db2");
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Show tables from current database(db2)" << endl;
+        try {
+            SessionDataSet dataSet = session->executeQueryStatement("SHOW 
TABLES");
+            Output(dataSet.getColumnNames());
+            while(dataSet.hasNext()) {
+                Output(dataSet.next());
+            }
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "Drop Database db1,db2" << endl;
+        try {
+            session->executeNonQueryStatement("DROP DATABASE db1");
+            session->executeNonQueryStatement("DROP DATABASE db2");
+        } catch (IoTDBException &e) {
+            cout << e.what() << endl;
+        }
+
+        cout << "session close\n" << endl;
+        session->close();
+
+        delete session;
+
+        cout << "finished!\n" << endl;
+    } catch (IoTDBConnectionException &e) {
+        cout << e.what() << endl;
+    } catch (IoTDBException &e) {
+        cout << e.what() << endl;
+    }
+    return 0;
+}
\ No newline at end of file
diff --git a/iotdb-client/client-cpp/pom.xml b/iotdb-client/client-cpp/pom.xml
index f358a2d9aea..2196fb5f234 100644
--- a/iotdb-client/client-cpp/pom.xml
+++ b/iotdb-client/client-cpp/pom.xml
@@ -163,6 +163,22 @@
                                     
<sourceFile>${project.basedir}/src/main/Session.cpp</sourceFile>
                                     
<destinationFile>${project.build.directory}/build/main/generated-sources-cpp/Session.cpp</destinationFile>
                                 </fileSet>
+                                <fileSet>
+                                    
<sourceFile>${project.basedir}/src/main/TableSession.h</sourceFile>
+                                    
<destinationFile>${project.build.directory}/build/main/generated-sources-cpp/TableSession.h</destinationFile>
+                                </fileSet>
+                                <fileSet>
+                                    
<sourceFile>${project.basedir}/src/main/TableSession.cpp</sourceFile>
+                                    
<destinationFile>${project.build.directory}/build/main/generated-sources-cpp/TableSession.cpp</destinationFile>
+                                </fileSet>
+                                <fileSet>
+                                    
<sourceFile>${project.basedir}/src/main/TableSessionBuilder.h</sourceFile>
+                                    
<destinationFile>${project.build.directory}/build/main/generated-sources-cpp/TableSessionBuilder.h</destinationFile>
+                                </fileSet>
+                                <fileSet>
+                                    
<sourceFile>${project.basedir}/src/main/AbstractSessionBuilder.h</sourceFile>
+                                    
<destinationFile>${project.build.directory}/build/main/generated-sources-cpp/AbstractSessionBuilder.h</destinationFile>
+                                </fileSet>
                             </fileSets>
                         </configuration>
                     </execution>
diff --git a/iotdb-client/client-cpp/src/main/AbstractSessionBuilder.h 
b/iotdb-client/client-cpp/src/main/AbstractSessionBuilder.h
new file mode 100644
index 00000000000..1b4d9a729a1
--- /dev/null
+++ b/iotdb-client/client-cpp/src/main/AbstractSessionBuilder.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+#ifndef IOTDB_ABSTRACTSESSIONBUILDER_H
+#define IOTDB_ABSTRACTSESSIONBUILDER_H
+
+#include <string>
+
+class AbstractSessionBuilder {
+public:
+    std::string host = "localhost";
+    int rpcPort = 6667;
+    std::string username = "root";
+    std::string password = "root";
+    std::string zoneId = "";
+    int fetchSize = 10000;
+    std::string sqlDialect = "tree";
+    std::string database = "";
+};
+
+#endif // IOTDB_ABSTRACTSESSIONBUILDER_H
\ No newline at end of file
diff --git a/iotdb-client/client-cpp/src/main/Session.cpp 
b/iotdb-client/client-cpp/src/main/Session.cpp
index 3a11da9ac7e..8581e7a0212 100644
--- a/iotdb-client/client-cpp/src/main/Session.cpp
+++ b/iotdb-client/client-cpp/src/main/Session.cpp
@@ -34,15 +34,15 @@ static const int64_t QUERY_TIMEOUT_MS = -1;
 LogLevelType LOG_LEVEL = LEVEL_DEBUG;
 
 TSDataType::TSDataType getTSDataTypeFromString(const string &str) {
-    // BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT, NULLTYPE
+    // BOOLEAN, INT32, INT64, FLOAT, DOUBLE, TEXT, STRING, BLOB, TIMESTAMP, 
DATE, NULLTYPE
     if (str == "BOOLEAN") return TSDataType::BOOLEAN;
-    else if (str == "INT32") return TSDataType::INT32;
-    else if (str == "INT64") return TSDataType::INT64;
+    else if (str == "INT32" || str == "DATE") return TSDataType::INT32;
+    else if (str == "INT64" || str == "TIMESTAMP") return TSDataType::INT64;
     else if (str == "FLOAT") return TSDataType::FLOAT;
     else if (str == "DOUBLE") return TSDataType::DOUBLE;
-    else if (str == "TEXT") return TSDataType::TEXT;
+    else if (str == "TEXT" || str == "STRING" || str == "BLOB") return 
TSDataType::TEXT;
     else if (str == "NULLTYPE") return TSDataType::NULLTYPE;
-    return TSDataType::TEXT;
+    return TSDataType::INVALID_DATATYPE;
 }
 
 void RpcUtils::verifySuccess(const TSStatus &status) {
@@ -181,56 +181,6 @@ void Tablet::deleteColumns() {
     }
 }
 
-void Tablet::addValue(size_t schemaId, size_t rowIndex, void* value) {
-    if (schemaId >= schemas.size()) {
-        char tmpStr[100];
-        sprintf(tmpStr, "Tablet::addValue(), schemaId >= schemas.size(). 
schemaId=%ld, schemas.size()=%ld.", schemaId, schemas.size());
-        throw std::out_of_range(tmpStr);
-    }
-
-    if (rowIndex >= rowSize) {
-        char tmpStr[100];
-        sprintf(tmpStr, "Tablet::addValue(), rowIndex >= rowSize. 
rowIndex=%ld, rowSize.size()=%ld.", rowIndex, rowSize);
-        throw std::out_of_range(tmpStr);
-    }
-
-    TSDataType::TSDataType dataType = schemas[schemaId].second;
-    switch (dataType) {
-        case TSDataType::BOOLEAN: {
-            bool* valueBuf = (bool*)(values[schemaId]);
-            valueBuf[rowIndex] = *((bool*)value);
-            break;
-        }
-        case TSDataType::INT32: {
-            int* valueBuf = (int*)(values[schemaId]);
-            valueBuf[rowIndex] = *((int*)value);
-            break;
-        }
-        case TSDataType::INT64: {
-            int64_t* valueBuf = (int64_t*)(values[schemaId]);
-            valueBuf[rowIndex] = *((int64_t*)value);
-            break;
-        }
-        case TSDataType::FLOAT: {
-            float* valueBuf = (float*)(values[schemaId]);
-            valueBuf[rowIndex] = *((float*)value);
-            break;
-        }
-        case TSDataType::DOUBLE: {
-            double* valueBuf = (double*)(values[schemaId]);
-            valueBuf[rowIndex] = *((double*)value);
-            break;
-        }
-        case TSDataType::TEXT: {
-            string* valueBuf = (string*)(values[schemaId]);
-            valueBuf[rowIndex] = *(string*)value;
-            break;
-        }
-        default:
-            throw UnSupportedDataTypeException(string("Data type ") + 
to_string(dataType) + " is not supported.");
-    }
-}
-
 void Tablet::reset() {
     rowSize = 0;
     for (size_t i = 0; i < schemas.size(); i++) {
@@ -876,6 +826,10 @@ void Session::open(bool enableRPCCompression, int 
connectionTimeoutInMs) {
 
     std::map<std::string, std::string> configuration;
     configuration["version"] = getVersionString(version);
+    configuration["sql_dialect"] = sqlDialect;
+    if (database != "") {
+        configuration["db"] = database;
+    }
 
     TSOpenSessionReq openReq;
     openReq.__set_username(username);
@@ -1386,6 +1340,35 @@ void Session::insertTablet(Tablet &tablet, bool sorted) {
     insertTablet(request);
 }
 
+void Session::insertRelationalTablet(Tablet &tablet, bool sorted) {
+    TSInsertTabletReq request;
+    buildInsertTabletReq(request, sessionId, tablet, sorted);
+    request.__set_writeToTable(true);
+    std::vector<int8_t> columnCategories;
+    for (auto &category: tablet.columnTypes) {
+        columnCategories.push_back(static_cast<int8_t>(category));
+    }
+    request.__set_columnCategories(columnCategories);
+    try {
+        TSStatus respStatus;
+        client->insertTablet(respStatus, request);
+        RpcUtils::verifySuccess(respStatus);
+    } catch (const TTransportException &e) {
+        log_debug(e.what());
+        throw IoTDBConnectionException(e.what());
+    } catch (const IoTDBException &e) {
+        log_debug(e.what());
+        throw;
+    } catch (const exception &e) {
+        log_debug(e.what());
+        throw IoTDBException(e.what());
+    }
+}
+
+void Session::insertRelationalTablet(Tablet &tablet) {
+    insertRelationalTablet(tablet, false);
+}
+
 void Session::insertAlignedTablet(Tablet &tablet) {
     insertAlignedTablet(tablet, false);
 }
@@ -1653,6 +1636,18 @@ void Session::deleteStorageGroups(const vector<string> 
&storageGroups) {
     }
 }
 
+void Session::createDatabase(const string &database) {
+    this->setStorageGroup(database);
+}
+
+void Session::deleteDatabase(const string &database) {
+    this->deleteStorageGroups(vector<string>{database});
+}
+
+void Session::deleteDatabases(const vector<string> &databases) {
+    this->deleteStorageGroups(databases);
+}
+
 void Session::createTimeseries(const string &path,
                                TSDataType::TSDataType dataType,
                                TSEncoding::TSEncoding encoding,
@@ -1917,7 +1912,10 @@ void Session::executeNonQueryStatement(const string 
&sql) {
     req.__set_timeout(0);  //0 means no timeout. This value keep consistent to 
JAVA SDK.
     TSExecuteStatementResp resp;
     try {
-        client->executeUpdateStatement(resp, req);
+        client->executeUpdateStatementV2(resp, req);
+        if (resp.database != "") {
+            database = resp.database;
+        }
         RpcUtils::verifySuccess(resp.status);
     } catch (const TTransportException &e) {
         log_debug(e.what());
diff --git a/iotdb-client/client-cpp/src/main/Session.h 
b/iotdb-client/client-cpp/src/main/Session.h
index d6c3bfc9a23..80f93a41d24 100644
--- a/iotdb-client/client-cpp/src/main/Session.h
+++ b/iotdb-client/client-cpp/src/main/Session.h
@@ -41,6 +41,7 @@
 #include <thrift/transport/TTransportException.h>
 #include <thrift/transport/TBufferTransports.h>
 #include "IClientRPCService.h"
+#include "AbstractSessionBuilder.h"
 
 //== For compatible with Windows OS ==
 #ifndef LONG_LONG_MIN
@@ -134,6 +135,15 @@ public:
     explicit UnSupportedDataTypeException(const std::string &m) : 
IoTDBException("UnSupported dataType: " + m) {}
 };
 
+class SchemaNotFoundException : public IoTDBException {
+public:
+    SchemaNotFoundException() {}
+
+    explicit SchemaNotFoundException(const char *m) : IoTDBException(m) {}
+
+    explicit SchemaNotFoundException(const std::string &m) : IoTDBException(m) 
{}
+};
+
 namespace Version {
     enum Version {
         V_0_12, V_0_13, V_1_0
@@ -164,7 +174,8 @@ namespace TSDataType {
         DOUBLE = (char) 4,
         TEXT = (char) 5,
         VECTOR = (char) 6,
-        NULLTYPE = (char) 7
+        NULLTYPE = (char) 254,
+        INVALID_DATATYPE = (char) 255
     };
 }
 
@@ -180,9 +191,8 @@ namespace TSEncoding {
         REGULAR = (char) 7,
         GORILLA = (char) 8,
         ZIGZAG = (char) 9,
-           CHIMP = (char) 11,
-           SPRINTZ = (char) 12,
-           RLBE = (char) 13
+           FREQ = (char) 10,
+        INVALID_ENCODING = (char) 255
     };
 }
 
@@ -536,6 +546,47 @@ public:
     Field() = default;
 };
 
+enum class ColumnCategory {
+    ID,
+    MEASUREMENT,
+    ATTRIBUTE
+};
+
+template<typename T, typename Target>
+const Target* safe_cast(const T& value) {
+    /*
+        Target Allowed Source Types
+        BOOLEAN        BOOLEAN
+        INT32  INT32
+        INT64  INT32 INT64
+        FLOAT  INT32 FLOAT
+        DOUBLE INT32 INT64 FLOAT DOUBLE
+        TEXT   TEXT
+    */
+    if (std::is_same<Target, T>::value) {
+        return (Target*)&value;
+    } else if (std::is_same<Target, int64_t>::value && std::is_same<T, 
int32_t>::value) {
+        int64_t tmp = *(int32_t*)&value;
+        return (Target*)&tmp;
+    } else if (std::is_same<Target, float>::value && std::is_same<T, 
int32_t>::value) {
+        float tmp = *(int32_t*)&value;
+        return (Target*)&tmp;
+    } else if (std::is_same<Target, double>::value && std::is_same<T, 
int32_t>::value) {
+        double tmp = *(int32_t*)&value;
+        return (Target*)&tmp;
+    } else if (std::is_same<Target, double>::value && std::is_same<T, 
int64_t>::value) {
+        double tmp = *(int64_t*)&value;
+        return (Target*)&tmp;
+    } else if (std::is_same<Target, double>::value && std::is_same<T, 
float>::value) {
+        double tmp = *(float*)&value;
+        return (Target*)&tmp;
+    } else {
+        throw UnSupportedDataTypeException("Parameter type " +
+                                           std::string(typeid(T).name()) + " 
cannot be converted to DataType" +
+                                           std::string(typeid(Target).name()));
+    }
+}
+
 /*
  * A tablet data of one device, the tablet contains multiple measurements of 
this device that share
  * the same time column.
@@ -560,6 +611,8 @@ private:
 public:
     std::string deviceId; // deviceId of this tablet
     std::vector<std::pair<std::string, TSDataType::TSDataType>> schemas; // 
the list of measurement schemas for creating the tablet
+    std::map<std::string, size_t> schemaNameIndex; // the map of schema name 
to index
+    std::vector<ColumnCategory> columnTypes; // the list of column types (used 
in table model)
     std::vector<int64_t> timestamps;   // timestamps in this tablet
     std::vector<void*> values; // each object is a primitive type array, which 
represents values of one measurement
     std::vector<BitMap> bitMaps; // each bitmap represents the existence of 
each value in the current column
@@ -580,6 +633,11 @@ public:
            const std::vector<std::pair<std::string, TSDataType::TSDataType>> 
&timeseries)
            : Tablet(deviceId, timeseries, DEFAULT_ROW_SIZE) {}
 
+    Tablet(const std::string &deviceId,
+           const std::vector<std::pair<std::string, TSDataType::TSDataType>> 
&timeseries,
+           const std::vector<ColumnCategory> &columnTypes)
+           : Tablet(deviceId, timeseries, columnTypes, DEFAULT_ROW_SIZE) {}
+
     /**
      * Return a tablet with the specified number of rows (maxBatchSize). Only
      * call this constructor directly for testing purposes. Tablet should 
normally
@@ -588,10 +646,16 @@ public:
      * @param deviceId     the name of the device specified to be written in
      * @param schemas   the list of measurement schemas for creating the row
      *                     batch
+     * @param columnTypes the list of column types (used in table model)
      * @param maxRowNumber the maximum number of rows for this tablet
      */
+    Tablet(const std::string &deviceId,
+        const std::vector<std::pair<std::string, TSDataType::TSDataType>> 
&schemas,
+        int maxRowNumber)
+        : Tablet(deviceId, schemas, 
std::vector<ColumnCategory>(schemas.size(), ColumnCategory::MEASUREMENT), 
maxRowNumber) {}
     Tablet(const std::string &deviceId, const 
std::vector<std::pair<std::string, TSDataType::TSDataType>> &schemas,
-           size_t maxRowNumber, bool _isAligned = false) : deviceId(deviceId), 
schemas(schemas),
+           const std::vector<ColumnCategory> columnTypes,
+           size_t maxRowNumber, bool _isAligned = false) : deviceId(deviceId), 
schemas(schemas), columnTypes(columnTypes),
                                                         
maxRowNumber(maxRowNumber), isAligned(_isAligned) {
         // create timestamp column
         timestamps.resize(maxRowNumber);
@@ -603,6 +667,10 @@ public:
         for (size_t i = 0; i < schemas.size(); i++) {
             bitMaps[i].resize(maxRowNumber);
         }
+        // create schemaNameIndex
+        for (size_t i = 0; i < schemas.size(); i++) {
+            schemaNameIndex[schemas[i].first] = i;
+        }
         this->rowSize = 0;
     }
 
@@ -614,7 +682,59 @@ public:
         }
     }
 
-    void addValue(size_t schemaId, size_t rowIndex, void *value);
+    template<typename T>
+    void addValue(size_t schemaId, size_t rowIndex, const T& value) {
+        if (schemaId >= schemas.size()) {
+            char tmpStr[100];
+            sprintf(tmpStr, "Tablet::addValue(), schemaId >= schemas.size(). 
schemaId=%ld, schemas.size()=%ld.", schemaId, schemas.size());
+            throw std::out_of_range(tmpStr);
+        }
+
+        if (rowIndex >= rowSize) {
+            char tmpStr[100];
+            sprintf(tmpStr, "Tablet::addValue(), rowIndex >= rowSize. 
rowIndex=%ld, rowSize.size()=%ld.", rowIndex, rowSize);
+            throw std::out_of_range(tmpStr);
+        }
+
+        TSDataType::TSDataType dataType = schemas[schemaId].second;
+        switch (dataType) {
+            case TSDataType::BOOLEAN: {
+                ((bool*)values[schemaId])[rowIndex] = *safe_cast<T, 
bool>(value);
+                break;
+            }
+            case TSDataType::INT32: {
+                ((int*)values[schemaId])[rowIndex] = *safe_cast<T, int>(value);
+                break;
+            }
+            case TSDataType::INT64: {
+                ((int64_t*)values[schemaId])[rowIndex] = *safe_cast<T, 
int64_t>(value);
+                break;
+            }
+            case TSDataType::FLOAT: {
+                ((float*)values[schemaId])[rowIndex] = *safe_cast<T, 
float>(value);
+                break;
+            }
+            case TSDataType::DOUBLE: {
+                ((double*)values[schemaId])[rowIndex] = *safe_cast<T, 
double>(value);
+                break;
+            }
+            case TSDataType::TEXT: {
+                ((string*)values[schemaId])[rowIndex] = *safe_cast<T, 
string>(value);
+                break;
+            }
+            default:
+                throw UnSupportedDataTypeException(string("Data type ") + 
to_string(dataType) + " is not supported.");
+        }
+    }
+
+    template<typename T>
+    void addValue(const string &schemaName, size_t rowIndex, const T& value) {
+        if (schemaNameIndex.find(schemaName) == schemaNameIndex.end()) {
+            throw SchemaNotFoundException(string("Schema ") + schemaName + " 
not found.");
+        }
+        size_t schemaId = schemaNameIndex[schemaName];
+        addValue(schemaId, rowIndex, value);
+    }
 
     void reset(); // Reset Tablet to the default state - set the rowSize to 0
 
@@ -973,6 +1093,8 @@ private:
     const static int DEFAULT_FETCH_SIZE = 10000;
     const static int DEFAULT_TIMEOUT_MS = 0;
     Version::Version version;
+    std::string sqlDialect = "tree"; // default sql dialect
+    std::string database;
 
 private:
     static bool checkSorted(const Tablet &tablet);
@@ -1044,8 +1166,37 @@ public:
         initZoneId();
     }
 
+    Session(AbstractSessionBuilder* builder) {
+        this->host = builder->host;
+        this->rpcPort = builder->rpcPort;
+        this->username = builder->username;
+        this->password = builder->password;
+        this->zoneId = builder->zoneId;
+        this->fetchSize = builder->fetchSize;
+        this->version = Version::V_1_0;
+        this->sqlDialect = builder->sqlDialect;
+        this->database = builder->database;
+        initZoneId();
+    }
+
     ~Session();
 
+    void setSqlDialect(const std::string &dialect){
+        this->sqlDialect = dialect;
+    }
+
+    void setDatabase(const std::string &database) {
+        this->database = database;
+    }
+
+    string getDatabase() {
+        return database;
+    }
+
+    void changeDatabase(string database) {
+        this->database = database;
+    }
+
     int64_t getSessionId();
 
     void open();
@@ -1124,6 +1275,10 @@ public:
 
     void insertTablet(Tablet &tablet, bool sorted);
 
+    void insertRelationalTablet(Tablet &tablet);
+
+    void insertRelationalTablet(Tablet &tablet, bool sorted);
+
     static void buildInsertTabletReq(TSInsertTabletReq &request, int64_t 
sessionId, Tablet &tablet, bool sorted);
 
     void insertTablet(const TSInsertTabletReq &request);
@@ -1165,6 +1320,12 @@ public:
 
     void deleteStorageGroups(const std::vector<std::string> &storageGroups);
 
+    void createDatabase(const std::string &database);
+
+    void deleteDatabase(const std::string &database);
+
+    void deleteDatabases(const std::vector<std::string> &databases);
+
     void createTimeseries(const std::string &path, TSDataType::TSDataType 
dataType, TSEncoding::TSEncoding encoding,
                           CompressionType::CompressionType compressor);
 
diff --git a/iotdb-client/client-cpp/src/main/TableSession.cpp 
b/iotdb-client/client-cpp/src/main/TableSession.cpp
new file mode 100644
index 00000000000..e1c6badc5f6
--- /dev/null
+++ b/iotdb-client/client-cpp/src/main/TableSession.cpp
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+// This file is a translation of the Java file 
iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSession.java
+
+#include "TableSession.h"
+
+void TableSession::insert(Tablet &tablet, bool sorted = false) {
+    session->insertRelationalTablet(tablet, sorted);
+}
+void TableSession::executeNonQueryStatement(const string &sql) {
+    session->executeNonQueryStatement(sql);
+}
+unique_ptr<SessionDataSet> TableSession::executeQueryStatement(const string 
&sql) {
+    return session->executeQueryStatement(sql);
+}
+unique_ptr<SessionDataSet> TableSession::executeQueryStatement(const string 
&sql, int64_t timeoutInMs) {
+    return session->executeQueryStatement(sql, timeoutInMs);
+}
+string TableSession::getDatabase() {
+    return session->getDatabase();
+}
+void TableSession::open(bool enableRPCCompression) {
+    session->open(enableRPCCompression);
+}
+void TableSession::close() {
+    session->close();
+}
\ No newline at end of file
diff --git a/iotdb-client/client-cpp/src/main/TableSession.h 
b/iotdb-client/client-cpp/src/main/TableSession.h
new file mode 100644
index 00000000000..d6e9e23bc9f
--- /dev/null
+++ b/iotdb-client/client-cpp/src/main/TableSession.h
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+// This file is a translation of the Java file 
iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSession.java
+
+#ifndef IOTDB_TABLESESSION_H
+#define IOTDB_TABLESESSION_H
+
+#include "Session.h"
+
+class TableSession {
+private:
+    Session* session;
+public:
+    TableSession(Session* session) {
+        this->session = session;
+    }
+    void insert(Tablet& tablet, bool sorted);
+    void executeNonQueryStatement(const std::string& sql);
+    unique_ptr<SessionDataSet> executeQueryStatement(const std::string& sql);
+    unique_ptr<SessionDataSet> executeQueryStatement(const std::string& sql, 
int64_t timeoutInMs);
+    string getDatabase();
+    void open(bool enableRPCCompression = false);
+    void close();
+};
+
+#endif // IOTDB_TABLESESSION_H
\ No newline at end of file
diff --git a/iotdb-client/client-cpp/src/main/TableSessionBuilder.h 
b/iotdb-client/client-cpp/src/main/TableSessionBuilder.h
new file mode 100644
index 00000000000..5c1b1a0a22e
--- /dev/null
+++ b/iotdb-client/client-cpp/src/main/TableSessionBuilder.h
@@ -0,0 +1,76 @@
+/*
+ * 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.
+ */
+
+// This file is a translation of the Java file 
iotdb-client/session/src/main/java/org/apache/iotdb/session/TableSessionBuilder.java
+
+#ifndef IOTDB_TABLESESSIONBUILDER_H
+#define IOTDB_TABLESESSIONBUILDER_H
+
+#include "TableSession.h"
+#include "AbstractSessionBuilder.h"
+
+class TableSessionBuilder : public AbstractSessionBuilder {
+    /*
+        std::string host;
+        int rpcPort;
+        std::string username;
+        std::string password;
+        std::string zoneId;
+        int fetchSize;
+        std::string sqlDialect = "tree"; // default sql dialect
+        std::string database;
+    */
+public:
+    TableSessionBuilder* host(const std::string &host) {
+        AbstractSessionBuilder::host = host;
+        return this;
+    }
+    TableSessionBuilder* rpcPort(int rpcPort) {
+        AbstractSessionBuilder::rpcPort = rpcPort;
+        return this;
+    }
+    TableSessionBuilder* username(const std::string &username) {
+        AbstractSessionBuilder::username = username;
+        return this;
+    }
+    TableSessionBuilder* password(const std::string &password) {
+        AbstractSessionBuilder::password = password;
+        return this;
+    }
+    TableSessionBuilder* zoneId(const std::string &zoneId) {
+        AbstractSessionBuilder::zoneId = zoneId;
+        return this;
+    }
+    TableSessionBuilder* fetchSize(int fetchSize) {
+        AbstractSessionBuilder::fetchSize = fetchSize;
+        return this;
+    }
+    TableSessionBuilder* database(const std::string &database) {
+        AbstractSessionBuilder::database = database;
+        return this;
+    }
+    TableSession* build() {
+        sqlDialect = "table";
+        Session* newSession = new Session(this);
+        newSession->open(false);
+        return new TableSession(newSession);
+    }
+};
+
+#endif // IOTDB_TABLESESSIONBUILDER_H
\ No newline at end of file
diff --git a/iotdb-client/client-cpp/src/test/CMakeLists.txt 
b/iotdb-client/client-cpp/src/test/CMakeLists.txt
index d38c975de20..186c08b634d 100644
--- a/iotdb-client/client-cpp/src/test/CMakeLists.txt
+++ b/iotdb-client/client-cpp/src/test/CMakeLists.txt
@@ -21,6 +21,7 @@ INCLUDE( CTest )
 SET(CMAKE_CXX_STANDARD 11)
 SET(CMAKE_CXX_STANDARD_REQUIRED ON)
 SET(TARGET_NAME session_tests)
+SET(TARGET_NAME_RELATIONAL session_relational_tests)
 SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall -g -O2")
 ENABLE_TESTING()
 
@@ -47,18 +48,26 @@ ELSE()
 ENDIF()
 
 ADD_EXECUTABLE(${TARGET_NAME} main.cpp cpp/sessionIT.cpp)
+ADD_EXECUTABLE(${TARGET_NAME_RELATIONAL} main_Relational.cpp 
cpp/sessionRelationalIT.cpp)
 
 # Link with shared library iotdb_session and pthread
 IF(MSVC)
     TARGET_LINK_LIBRARIES(${TARGET_NAME} iotdb_session ${THRIFT_STATIC_LIB})
+    TARGET_LINK_LIBRARIES(${TARGET_NAME_RELATIONAL} iotdb_session 
${THRIFT_STATIC_LIB})
 ELSE()
     TARGET_LINK_LIBRARIES(${TARGET_NAME} iotdb_session pthread)
+    TARGET_LINK_LIBRARIES(${TARGET_NAME_RELATIONAL} iotdb_session pthread)
 ENDIF()
+
+# Add Catch2 include directory
 TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME} PUBLIC ./catch2/)
+TARGET_INCLUDE_DIRECTORIES(${TARGET_NAME_RELATIONAL} PUBLIC ./catch2/)
 
 # Add 'sessionIT' to the project to be run by ctest
 IF(MSVC)
     ADD_TEST(NAME sessionIT CONFIGURATIONS Release COMMAND ${TARGET_NAME})
+    ADD_TEST(NAME sessionRelationalIT CONFIGURATIONS Release COMMAND 
${TARGET_NAME_RELATIONAL})
 ELSE()
     ADD_TEST(NAME sessionIT COMMAND ${TARGET_NAME})
+    ADD_TEST(NAME sessionRelationalIT COMMAND ${TARGET_NAME_RELATIONAL})
 ENDIF()
diff --git a/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp 
b/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
index 8016a4e37b3..aab43b60ead 100644
--- a/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
+++ b/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
@@ -274,7 +274,7 @@ TEST_CASE("Test insertTablet ", "[testInsertTablet]") {
         int row = tablet.rowSize++;
         tablet.timestamps[row] = time;
         for (int64_t i = 0; i < 3; i++) {
-            tablet.addValue(i, row, &i);
+            tablet.addValue(i, row, i);
         }
         if (tablet.rowSize == tablet.maxRowNumber) {
             session->insertTablet(tablet);
diff --git a/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp 
b/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
new file mode 100644
index 00000000000..b0f562f1199
--- /dev/null
+++ b/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
@@ -0,0 +1,117 @@
+/**
+ * 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.
+ */
+
+#include "catch.hpp"
+#include "TableSession.h"
+#include <math.h>
+
+using namespace std;
+
+extern TableSession *session;
+
+static int global_test_id = 0;
+class CaseReporter
+{
+public:
+    CaseReporter(const char *caseNameArg) : caseName(caseNameArg)
+    {
+        test_id = global_test_id++;
+        std::cout << "Test " << test_id << ": " << caseName << std::endl;
+    }
+    ~CaseReporter()
+    {
+        std::cout << "Test " << test_id << ": " << caseName << " Done"<< 
std::endl << std::endl;
+    }
+private:
+    const char *caseName;
+    int test_id;
+};
+
+TEST_CASE("Create table success", "[createTable]") {
+    // REQUIRE(true);
+    CaseReporter cr("createTable");
+    session->executeNonQueryStatement("CREATE DATABASE db1");
+    session->executeNonQueryStatement("CREATE DATABASE db2");
+    session->executeNonQueryStatement("USE \"db1\"");
+    REQUIRE(session->getDatabase() == "db1");
+    session->executeNonQueryStatement("CREATE TABLE table0 ("
+            "id1 string id,"
+            "attr1 string attribute,"
+            "m1 double measurement)");
+    unique_ptr<SessionDataSet> sessionDataSet = 
session->executeQueryStatement("SHOW TABLES");
+    sessionDataSet->setFetchSize(1024);
+    bool tableExist = false;
+    while (sessionDataSet->hasNext()) {
+        if (sessionDataSet->next()->fields[0].stringV == "table0") {
+            tableExist = true;
+            break;
+        }
+    }
+    REQUIRE(tableExist == true);
+}
+
+TEST_CASE("Test insertRelationalTablet", "[testInsertRelationalTablet]") {
+    CaseReporter cr("testInsertRelationalTablet");
+    session->executeNonQueryStatement("CREATE DATABASE IF NOT EXISTS db1");
+    session->executeNonQueryStatement("USE db1");
+    session->executeNonQueryStatement("CREATE TABLE table1 ("
+        "id1 string id,"
+        "attr1 string attribute,"
+        "m1 double measurement)");
+    vector<pair<string, TSDataType::TSDataType>> schemaList;
+    schemaList.push_back(make_pair("id1", TSDataType::TEXT));
+    schemaList.push_back(make_pair("attr1", TSDataType::TEXT));
+    schemaList.push_back(make_pair("m1", TSDataType::DOUBLE));
+    vector<ColumnCategory> columnTypes = {ColumnCategory::ID, 
ColumnCategory::ATTRIBUTE, ColumnCategory::MEASUREMENT};
+
+    int64_t timestamp = 0;
+    Tablet tablet("table1", schemaList, columnTypes, 15);
+
+    for (int row = 0; row < 15; row++) {
+        int rowIndex = tablet.rowSize++;
+        tablet.timestamps[rowIndex] = timestamp + row;
+        string data = "id:"; data += to_string(row);
+        tablet.addValue(0, rowIndex, data);
+        data = "attr:"; data += to_string(row);
+        tablet.addValue(1, rowIndex, data);
+        double value = row * 1.1;
+        tablet.addValue(2, rowIndex, value);
+        if (tablet.rowSize == tablet.maxRowNumber) {
+            session->insert(tablet, true);
+            tablet.reset();
+        }
+    }
+
+    if (tablet.rowSize != 0) {
+        session->insert(tablet, true);
+        tablet.reset();
+    }
+    session->executeNonQueryStatement("FLUSH");
+
+    int cnt = 0;
+    unique_ptr<SessionDataSet> sessionDataSet = 
session->executeQueryStatement("SELECT * FROM table1 order by time");
+    while (sessionDataSet->hasNext()) {
+        RowRecord *rowRecord = sessionDataSet->next();
+        REQUIRE(rowRecord->fields[1].stringV == string("id:") + 
to_string(cnt));
+        REQUIRE(rowRecord->fields[2].stringV == string("attr:") + 
to_string(cnt));
+        REQUIRE(fabs(rowRecord->fields[3].doubleV - cnt * 1.1) < 0.0001);
+        cnt++;
+    }
+    REQUIRE(cnt == 15);
+}
diff --git a/iotdb-client/client-cpp/src/test/main_Relational.cpp 
b/iotdb-client/client-cpp/src/test/main_Relational.cpp
new file mode 100644
index 00000000000..74c999baafb
--- /dev/null
+++ b/iotdb-client/client-cpp/src/test/main_Relational.cpp
@@ -0,0 +1,42 @@
+/**
+ * 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.
+ */
+
+#define CATCH_CONFIG_MAIN
+
+#include <catch.hpp>
+#include "TableSessionBuilder.h"
+
+TableSession *session = (new 
TableSessionBuilder())->host("127.0.0.1")->rpcPort(6667)->username("root")->password("root")->build();
+
+struct SessionListener : Catch::TestEventListenerBase {
+
+    using TestEventListenerBase::TestEventListenerBase;
+
+    void testCaseStarting(Catch::TestCaseInfo const &testInfo) override {
+        // Perform some setup before a test case is run
+        session->open();
+    }
+
+    void testCaseEnded(Catch::TestCaseStats const &testCaseStats) override {
+        // Tear-down after a test case is run
+        session->close();
+    }
+};
+
+CATCH_REGISTER_LISTENER( SessionListener )
\ No newline at end of file

Reply via email to