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>>
×eries)
: Tablet(deviceId, timeseries, DEFAULT_ROW_SIZE) {}
+ Tablet(const std::string &deviceId,
+ const std::vector<std::pair<std::string, TSDataType::TSDataType>>
×eries,
+ 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