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

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

commit 1f5e9ece7319ab05c74d82ab6f748b2bb9d6bdd0
Author: Hongzhi Gao <[email protected]>
AuthorDate: Tue Aug 5 16:42:05 2025 +0800

    cpp client datatype OBJECT (#16094)
    
    * cpp client datatype OBJECT
    
    * removed unused notes
---
 iotdb-client/client-cpp/src/main/Common.cpp        |  1 +
 iotdb-client/client-cpp/src/main/Common.h          |  3 +-
 .../client-cpp/src/main/IoTDBRpcDataSet.cpp        |  1 +
 iotdb-client/client-cpp/src/main/Session.cpp       | 30 +++++++++---
 iotdb-client/client-cpp/src/main/Session.h         | 54 +++++++++++++++++++++-
 .../client-cpp/src/main/SessionDataSet.cpp         |  2 +
 .../src/test/cpp/sessionRelationalIT.cpp           | 12 ++++-
 7 files changed, 92 insertions(+), 11 deletions(-)

diff --git a/iotdb-client/client-cpp/src/main/Common.cpp 
b/iotdb-client/client-cpp/src/main/Common.cpp
index cac4448b8e1..56dc9683057 100644
--- a/iotdb-client/client-cpp/src/main/Common.cpp
+++ b/iotdb-client/client-cpp/src/main/Common.cpp
@@ -89,6 +89,7 @@ TSDataType::TSDataType getDataTypeByStr(const std::string& 
typeStr) {
     if (typeStr == "DATE") return TSDataType::DATE;
     if (typeStr == "BLOB") return TSDataType::BLOB;
     if (typeStr == "STRING") return TSDataType::STRING;
+    if (typeStr == "OBJECT") return TSDataType::OBJECT;
     return TSDataType::UNKNOWN;
 }
 
diff --git a/iotdb-client/client-cpp/src/main/Common.h 
b/iotdb-client/client-cpp/src/main/Common.h
index 129e458c67b..aee44498605 100644
--- a/iotdb-client/client-cpp/src/main/Common.h
+++ b/iotdb-client/client-cpp/src/main/Common.h
@@ -95,7 +95,8 @@ enum TSDataType {
     TIMESTAMP = (char)8,
     DATE = (char)9,
     BLOB = (char)10,
-    STRING = (char)11
+    STRING = (char)11,
+    OBJECT = (char)12
 };
 }
 
diff --git a/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp 
b/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
index 7339d74c2c3..38bef0ab792 100644
--- a/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
+++ b/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
@@ -448,6 +448,7 @@ std::string 
IoTDBRpcDataSet::getStringByTsBlockColumnIndexAndDataType(int32_t in
         return 
std::to_string(curTsBlock_->getColumn(index)->getDouble(tsBlockIndex_));
     case TSDataType::TEXT:
     case TSDataType::STRING:
+    case TSDataType::OBJECT:
     case TSDataType::BLOB: {
         auto binary = curTsBlock_->getColumn(index)->getBinary(tsBlockIndex_);
         return binary->getStringValue();
diff --git a/iotdb-client/client-cpp/src/main/Session.cpp 
b/iotdb-client/client-cpp/src/main/Session.cpp
index 8182a67cccb..da1263527d1 100644
--- a/iotdb-client/client-cpp/src/main/Session.cpp
+++ b/iotdb-client/client-cpp/src/main/Session.cpp
@@ -59,6 +59,8 @@ TSDataType::TSDataType getTSDataTypeFromString(const string& 
str) {
         return TSDataType::BLOB;
     } else if (str == "STRING") {
         return TSDataType::STRING;
+    } else if (str == "OBJECT") {
+        return TSDataType::OBJECT;
     }
     return TSDataType::UNKNOWN;
 }
@@ -88,6 +90,7 @@ void Tablet::createColumns() {
             break;
         case TSDataType::STRING:
         case TSDataType::BLOB:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT:
             values[i] = new string[maxRowNumber];
             break;
@@ -135,6 +138,7 @@ void Tablet::deleteColumns() {
         }
         case TSDataType::STRING:
         case TSDataType::BLOB:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT: {
             string* valueBuf = (string*)(values[i]);
             delete[] valueBuf;
@@ -182,6 +186,7 @@ void Tablet::deepCopyTabletColValue(void* const* srcPtr, 
void** destPtr, TSDataT
     }
     case TSDataType::STRING:
     case TSDataType::TEXT:
+    case TSDataType::OBJECT:
     case TSDataType::BLOB: {
         *destPtr = new std::string[maxRowNumber];
         std::string* srcStr = static_cast<std::string*>(src);
@@ -232,6 +237,7 @@ size_t Tablet::getValueByteSize() {
             break;
         case TSDataType::STRING:
         case TSDataType::BLOB:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT: {
             valueOccupation += rowSize * 4;
             string* valueBuf = (string*)(values[i]);
@@ -361,6 +367,7 @@ string SessionUtils::getValue(const Tablet& tablet) {
         }
         case TSDataType::STRING:
         case TSDataType::BLOB:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT: {
             string* valueBuf = (string*)(tablet.values[i]);
             for (size_t index = 0; index < tablet.rowSize; index++) {
@@ -582,6 +589,7 @@ void Session::sortTablet(Tablet& tablet) {
         }
         case TSDataType::STRING:
         case TSDataType::BLOB:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT: {
             sortValuesList((string*)(tablet.values[i]), index, tablet.rowSize);
             break;
@@ -654,6 +662,7 @@ Session::putValuesIntoBuffer(const 
vector<TSDataType::TSDataType>& types, const
             break;
         case TSDataType::STRING:
         case TSDataType::BLOB:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT: {
             int32_t len = (uint32_t)strlen(values[i]);
             appendValues(buf, (char*)(&len), sizeof(uint32_t));
@@ -689,6 +698,8 @@ int8_t Session::getDataTypeNumber(TSDataType::TSDataType 
type) {
         return 10;
     case TSDataType::STRING:
         return 11;
+    case TSDataType::OBJECT:
+        return 12;
     default:
         return -1;
     }
@@ -1352,16 +1363,20 @@ void Session::buildInsertTabletReq(TSInsertTabletReq& 
request, Tablet& tablet, b
         sortTablet(tablet);
     }
 
-    request.prefixPath = tablet.deviceId;
+    request.__set_prefixPath(tablet.deviceId);
 
-    request.measurements.reserve(tablet.schemas.size());
-    request.types.reserve(tablet.schemas.size());
+    std::vector<std::string> reqMeasurements;
+    reqMeasurements.reserve(tablet.schemas.size());
+    std::vector<int32_t> types;
+    types.reserve(tablet.schemas.size());
     for (pair<string, TSDataType::TSDataType> schema : tablet.schemas) {
-        request.measurements.push_back(schema.first);
-        request.types.push_back(schema.second);
+        reqMeasurements.push_back(schema.first);
+        types.push_back(schema.second);
     }
-    request.values = move(SessionUtils::getValue(tablet));
-    request.timestamps = move(SessionUtils::getTime(tablet));
+    request.__set_measurements(reqMeasurements);
+    request.__set_types(types);
+    request.__set_values(SessionUtils::getValue(tablet));
+    request.__set_timestamps(SessionUtils::getTime(tablet));
     request.__set_size(tablet.rowSize);
     request.__set_isAligned(tablet.isAligned);
 }
@@ -1446,6 +1461,7 @@ void Session::insertRelationalTablet(Tablet& tablet, bool 
sorted) {
                 }
                 case TSDataType::STRING:
                 case TSDataType::TEXT:
+                case TSDataType::OBJECT:
                 case TSDataType::BLOB: {
                     currentTablet.addValue(tablet.schemas[col].first, rowIndex,
                         *(string*)tablet.getValue(col, row, 
tablet.schemas[col].second));
diff --git a/iotdb-client/client-cpp/src/main/Session.h 
b/iotdb-client/client-cpp/src/main/Session.h
index 35c05fad22c..4b901d5b20f 100644
--- a/iotdb-client/client-cpp/src/main/Session.h
+++ b/iotdb-client/client-cpp/src/main/Session.h
@@ -322,6 +322,58 @@ public:
         }
     }
 
+    // Add a Binary value with extra metadata: [isEOF (1 byte)] + [offset (8 
bytes)] + [actual content]
+    void addValue(size_t schemaId, size_t rowIndex, bool isEOF, int64_t 
offset, const std::vector<uint8_t>& content) {
+        // Check schemaId bounds
+        if (schemaId >= schemas.size()) {
+            char tmpStr[100];
+            sprintf(tmpStr,
+                    "Tablet::addBinaryValueWithMeta(), schemaId >= 
schemas.size(). schemaId=%ld, schemas.size()=%ld.",
+                    schemaId, schemas.size());
+            throw std::out_of_range(tmpStr);
+        }
+
+        // Check rowIndex bounds
+        if (rowIndex >= rowSize) {
+            char tmpStr[100];
+            sprintf(tmpStr, "Tablet::addBinaryValueWithMeta(), rowIndex >= 
rowSize. rowIndex=%ld, rowSize=%ld.",
+                    rowIndex, rowSize);
+            throw std::out_of_range(tmpStr);
+        }
+
+        TSDataType::TSDataType dataType = schemas[schemaId].second;
+        if (dataType != TSDataType::OBJECT) {
+            throw std::invalid_argument("The data type of schemaId " + 
std::to_string(schemaId) + " is not OBJECT.");
+        }
+
+        // Create a byte array of size [1 (isEOF) + 8 (offset) + content size]
+        std::vector<uint8_t> val(content.size() + 9);
+
+        // Write the isEOF flag (1 byte)
+        val[0] = isEOF ? 1 : 0;
+
+        // Write the 8-byte offset in big-endian order
+        for (int i = 0; i < 8; ++i) {
+            val[1 + i] = static_cast<uint8_t>((offset >> (56 - i * 8)) & 0xFF);
+        }
+
+        // Append the content bytes
+        std::copy(content.begin(), content.end(), val.begin() + 9);
+
+        // Cast the value array and assign the Binary data (stored as string)
+        std::string valEncoded = 
std::string(reinterpret_cast<char*>(val.data()), val.size());
+        safe_cast<string, string>(valEncoded, 
((string*)values[schemaId])[rowIndex]);
+    }
+
+    void addValue(const string& schemaName, size_t rowIndex, bool isEOF, 
int64_t offset,
+                  const std::vector<uint8_t>& content) {
+        if (schemaNameIndex.find(schemaName) == schemaNameIndex.end()) {
+            throw SchemaNotFoundException(string("Schema ") + schemaName + " 
not found.");
+        }
+        size_t schemaId = schemaNameIndex[schemaName];
+        addValue(schemaId, rowIndex, isEOF, offset, content);
+    }
+
     template <typename T>
     void addValue(const string& schemaName, size_t rowIndex, const T& value) {
         if (schemaNameIndex.find(schemaName) == schemaNameIndex.end()) {
@@ -331,7 +383,6 @@ public:
         addValue(schemaId, rowIndex, value);
     }
 
-
     void* getValue(size_t schemaId, size_t rowIndex, TSDataType::TSDataType 
dataType) {
         if (schemaId >= schemas.size()) {
             throw std::out_of_range("Tablet::getValue schemaId out of range: "
@@ -358,6 +409,7 @@ public:
             return &(reinterpret_cast<double*>(values[schemaId])[rowIndex]);
         case TSDataType::BLOB:
         case TSDataType::STRING:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT:
             return 
&(reinterpret_cast<std::string*>(values[schemaId])[rowIndex]);
         default:
diff --git a/iotdb-client/client-cpp/src/main/SessionDataSet.cpp 
b/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
index 048d5340916..0cdd13402e4 100644
--- a/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
+++ b/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
@@ -98,6 +98,7 @@ std::string RowRecord::toString() {
             break;
         case TSDataType::BLOB:
         case TSDataType::STRING:
+        case TSDataType::OBJECT:
         case TSDataType::TEXT:
             if (!fields[i].stringV.is_initialized()) {
                 ret.append("null");
@@ -268,6 +269,7 @@ shared_ptr<RowRecord> 
SessionDataSet::constructRowRecordFromValueArray() {
             case TSDataType::TEXT:
             case TSDataType::BLOB:
             case TSDataType::STRING:
+            case TSDataType::OBJECT:
                 field.stringV = 
iotdbRpcDataSet_->getBinary(columnName)->getStringValue();
                 break;
             default:
diff --git a/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp 
b/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
index 94f956b56ea..8dff31ba7f4 100644
--- a/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
+++ b/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
@@ -159,7 +159,8 @@ TEST_CASE("Test RelationalTabletTsblockRead", 
"[testRelationalTabletTsblockRead]
         "field7 TIMESTAMP field,"
         "field8 DATE field,"
         "field9 BLOB field,"
-        "field10 STRING field)");
+        "field10 STRING field,"
+        "field11 OBJECT field)");
 
     vector<pair<string, TSDataType::TSDataType>> schemaList;
     schemaList.push_back(make_pair("field1", TSDataType::BOOLEAN));
@@ -172,8 +173,9 @@ TEST_CASE("Test RelationalTabletTsblockRead", 
"[testRelationalTabletTsblockRead]
     schemaList.push_back(make_pair("field8", TSDataType::DATE));
     schemaList.push_back(make_pair("field9", TSDataType::BLOB));
     schemaList.push_back(make_pair("field10", TSDataType::STRING));
+    schemaList.push_back(make_pair("field11", TSDataType::OBJECT));
 
-    vector<ColumnCategory> columnTypes(10, ColumnCategory::FIELD);
+    vector<ColumnCategory> columnTypes(11, ColumnCategory::FIELD);
 
     int64_t timestamp = 0;
     int maxRowNumber = 50000;
@@ -192,6 +194,9 @@ TEST_CASE("Test RelationalTabletTsblockRead", 
"[testRelationalTabletTsblockRead]
         tablet.addValue(7, rowIndex, boost::gregorian::date(2025, 5, 15));
         tablet.addValue(8, rowIndex, "blob_" + to_string(row));
         tablet.addValue(9, rowIndex, "string_" + to_string(row));
+        vector<uint8_t> rawData = {0x01, 0x02, 0x03, 0x04};
+        // always non-null
+        tablet.addValue(10, rowIndex, true, 0, rawData);
 
         if (row % 2 == 0) {
             for (int col = 0; col <= 9; col++) {
@@ -227,6 +232,7 @@ TEST_CASE("Test RelationalTabletTsblockRead", 
"[testRelationalTabletTsblockRead]
             REQUIRE_FALSE(dataIter.getDateByIndex(9).is_initialized());
             REQUIRE_FALSE(dataIter.getStringByIndex(10).is_initialized());
             REQUIRE_FALSE(dataIter.getStringByIndex(11).is_initialized());
+            REQUIRE_FALSE(!dataIter.getStringByIndex(12).is_initialized());
         } else {
             REQUIRE(dataIter.getLongByIndex(1).value() == timestamp + rowNum);
             REQUIRE(dataIter.getBooleanByIndex(2).value() == (rowNum % 2 == 
0));
@@ -239,6 +245,8 @@ TEST_CASE("Test RelationalTabletTsblockRead", 
"[testRelationalTabletTsblockRead]
             REQUIRE(dataIter.getDateByIndex(9).value() == 
boost::gregorian::date(2025, 5, 15));
             REQUIRE(dataIter.getStringByIndex(10).value() == "blob_" + 
to_string(rowNum));
             REQUIRE(dataIter.getStringByIndex(11).value() == "string_" + 
to_string(rowNum));
+            // [isEOF (1 byte)] + [offset (8 bytes)] + [content (4 bytes)]
+            REQUIRE(dataIter.getStringByIndex(12).value() != "");
         }
         rowNum++;
     }

Reply via email to