Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions iotdb-client/client-cpp/src/main/Common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
3 changes: 2 additions & 1 deletion iotdb-client/client-cpp/src/main/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,8 @@ enum TSDataType {
TIMESTAMP = (char)8,
DATE = (char)9,
BLOB = (char)10,
STRING = (char)11
STRING = (char)11,
OBJECT = (char)12
};
}

Expand Down
1 change: 1 addition & 0 deletions iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
30 changes: 23 additions & 7 deletions iotdb-client/client-cpp/src/main/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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]);
Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -1295,16 +1306,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);
}
Expand Down Expand Up @@ -1389,6 +1404,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));
Expand Down
55 changes: 54 additions & 1 deletion iotdb-client/client-cpp/src/main/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,59 @@ class Tablet {
}
}

// 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);
}

// Validate data type: must be TEXT, STRING, or BLOB
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()) {
Expand All @@ -331,7 +384,6 @@ class Tablet {
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: "
Expand All @@ -358,6 +410,7 @@ class Tablet {
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:
Expand Down
2 changes: 2 additions & 0 deletions iotdb-client/client-cpp/src/main/SessionDataSet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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:
Expand Down
12 changes: 10 additions & 2 deletions iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,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));
Expand All @@ -148,8 +149,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;
Expand All @@ -168,6 +170,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++) {
Expand Down Expand Up @@ -203,6 +208,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));
Expand All @@ -215,6 +221,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++;
}
Expand Down
Loading