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 3e6aaa3a4cc fix cpp client processing null value (#15700)
3e6aaa3a4cc is described below
commit 3e6aaa3a4cc3a69b3f09c97fe18a294235cce6aa
Author: Hongzhi Gao <[email protected]>
AuthorDate: Mon Jun 16 12:24:12 2025 +0800
fix cpp client processing null value (#15700)
---
iotdb-client/client-cpp/src/main/Common.h | 15 ++--
.../client-cpp/src/main/IoTDBRpcDataSet.cpp | 68 +++++++++---------
iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.h | 42 +++++------
iotdb-client/client-cpp/src/main/NodesSupplier.cpp | 16 +++--
.../client-cpp/src/main/SessionDataSet.cpp | 78 ++++++++++++++-------
iotdb-client/client-cpp/src/main/SessionDataSet.h | 32 ++++-----
iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp | 66 +++++++++---------
.../src/test/cpp/sessionRelationalIT.cpp | 81 ++++++++++++++++++----
8 files changed, 244 insertions(+), 154 deletions(-)
diff --git a/iotdb-client/client-cpp/src/main/Common.h
b/iotdb-client/client-cpp/src/main/Common.h
index a9f4552ecc5..aa583cb6ba8 100644
--- a/iotdb-client/client-cpp/src/main/Common.h
+++ b/iotdb-client/client-cpp/src/main/Common.h
@@ -30,6 +30,7 @@
#include <thrift/transport/TBufferTransports.h>
#include <boost/date_time/gregorian/gregorian.hpp>
#include <cstdint>
+#include <boost/optional/optional.hpp>
#include "client_types.h"
#include "common_types.h"
@@ -178,13 +179,13 @@ enum TSStatusCode {
class Field {
public:
TSDataType::TSDataType dataType = TSDataType::UNKNOWN;
- bool boolV{};
- int intV{};
- boost::gregorian::date dateV;
- int64_t longV{};
- float floatV{};
- double doubleV{};
- std::string stringV;
+ boost::optional<bool> boolV;
+ boost::optional<int> intV;
+ boost::optional<boost::gregorian::date> dateV;
+ boost::optional<int64_t> longV;
+ boost::optional<float> floatV;
+ boost::optional<double> doubleV;
+ boost::optional<std::string> stringV;
explicit Field(TSDataType::TSDataType a) {
dataType = a;
diff --git a/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
b/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
index 1d55b7e0b9a..8fa020851fe 100644
--- a/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
+++ b/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.cpp
@@ -22,6 +22,9 @@
#include <stdexcept>
#include "IoTDBRpcDataSet.h"
+
+#include <boost/optional/optional.hpp>
+
#include "Column.h"
const int32_t IoTDBRpcDataSet::startIndex = 2;
@@ -257,17 +260,17 @@ bool IoTDBRpcDataSet::isNull(int32_t index, int32_t
rowNum) {
return index >= 0 && curTsBlock_->getColumn(index)->isNull(rowNum);
}
-bool IoTDBRpcDataSet::getBooleanByIndex(int32_t columnIndex) {
+boost::optional<bool> IoTDBRpcDataSet::getBooleanByIndex(int32_t columnIndex) {
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getBooleanByTsBlockColumnIndex(index);
}
-bool IoTDBRpcDataSet::getBoolean(const std::string& columnName) {
+boost::optional<bool> IoTDBRpcDataSet::getBoolean(const std::string&
columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getBooleanByTsBlockColumnIndex(index);
}
-bool IoTDBRpcDataSet::getBooleanByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
+boost::optional<bool> IoTDBRpcDataSet::getBooleanByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
checkRecord();
if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
lastReadWasNull_ = false;
@@ -275,21 +278,21 @@ bool
IoTDBRpcDataSet::getBooleanByTsBlockColumnIndex(int32_t tsBlockColumnIndex)
}
else {
lastReadWasNull_ = true;
- return false;
+ return boost::none;
}
}
-double IoTDBRpcDataSet::getDoubleByIndex(int32_t columnIndex) {
+boost::optional<double> IoTDBRpcDataSet::getDoubleByIndex(int32_t columnIndex)
{
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getDoubleByTsBlockColumnIndex(index);
}
-double IoTDBRpcDataSet::getDouble(const std::string& columnName) {
+boost::optional<double> IoTDBRpcDataSet::getDouble(const std::string&
columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getDoubleByTsBlockColumnIndex(index);
}
-double IoTDBRpcDataSet::getDoubleByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
+boost::optional<double> IoTDBRpcDataSet::getDoubleByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
checkRecord();
if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
lastReadWasNull_ = false;
@@ -297,21 +300,21 @@ double
IoTDBRpcDataSet::getDoubleByTsBlockColumnIndex(int32_t tsBlockColumnIndex
}
else {
lastReadWasNull_ = true;
- return 0.0;
+ return boost::none;
}
}
-float IoTDBRpcDataSet::getFloatByIndex(int32_t columnIndex) {
+boost::optional<float> IoTDBRpcDataSet::getFloatByIndex(int32_t columnIndex) {
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getFloatByTsBlockColumnIndex(index);
}
-float IoTDBRpcDataSet::getFloat(const std::string& columnName) {
+boost::optional<float> IoTDBRpcDataSet::getFloat(const std::string&
columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getFloatByTsBlockColumnIndex(index);
}
-float IoTDBRpcDataSet::getFloatByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
+boost::optional<float> IoTDBRpcDataSet::getFloatByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
checkRecord();
if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
lastReadWasNull_ = false;
@@ -319,21 +322,21 @@ float
IoTDBRpcDataSet::getFloatByTsBlockColumnIndex(int32_t tsBlockColumnIndex)
}
else {
lastReadWasNull_ = true;
- return 0.0f;
+ return boost::none;
}
}
-int32_t IoTDBRpcDataSet::getIntByIndex(int32_t columnIndex) {
+boost::optional<int32_t> IoTDBRpcDataSet::getIntByIndex(int32_t columnIndex) {
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getIntByTsBlockColumnIndex(index);
}
-int32_t IoTDBRpcDataSet::getInt(const std::string& columnName) {
+boost::optional<int32_t> IoTDBRpcDataSet::getInt(const std::string&
columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getIntByTsBlockColumnIndex(index);
}
-int32_t IoTDBRpcDataSet::getIntByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
+boost::optional<int32_t> IoTDBRpcDataSet::getIntByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
checkRecord();
if (!isNull(tsBlockColumnIndex, tsBlockIndex_)) {
lastReadWasNull_ = false;
@@ -345,21 +348,21 @@ int32_t
IoTDBRpcDataSet::getIntByTsBlockColumnIndex(int32_t tsBlockColumnIndex)
}
else {
lastReadWasNull_ = true;
- return 0;
+ return boost::none;
}
}
-int64_t IoTDBRpcDataSet::getLongByIndex(int32_t columnIndex) {
+boost::optional<int64_t> IoTDBRpcDataSet::getLongByIndex(int32_t columnIndex) {
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getLongByTsBlockColumnIndex(index);
}
-int64_t IoTDBRpcDataSet::getLong(const std::string& columnName) {
+boost::optional<int64_t> IoTDBRpcDataSet::getLong(const std::string&
columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getLongByTsBlockColumnIndex(index);
}
-int64_t IoTDBRpcDataSet::getLongByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
+boost::optional<int64_t> IoTDBRpcDataSet::getLongByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
checkRecord();
if (tsBlockColumnIndex < 0) {
lastReadWasNull_ = false;
@@ -375,7 +378,7 @@ int64_t
IoTDBRpcDataSet::getLongByTsBlockColumnIndex(int32_t tsBlockColumnIndex)
}
else {
lastReadWasNull_ = true;
- return 0;
+ return boost::none;
}
}
@@ -401,25 +404,25 @@ std::shared_ptr<Binary>
IoTDBRpcDataSet::getBinaryByTsBlockColumnIndex(int32_t t
}
}
-std::string IoTDBRpcDataSet::getStringByIndex(int32_t columnIndex) {
+boost::optional<std::string> IoTDBRpcDataSet::getStringByIndex(int32_t
columnIndex) {
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getStringByTsBlockColumnIndex(index);
}
-std::string IoTDBRpcDataSet::getString(const std::string& columnName) {
+boost::optional<std::string> IoTDBRpcDataSet::getString(const std::string&
columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getStringByTsBlockColumnIndex(index);
}
-std::string IoTDBRpcDataSet::getStringByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
+boost::optional<std::string>
IoTDBRpcDataSet::getStringByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
checkRecord();
- if (tsBlockColumnIndex == -1) {
+ if (tsBlockColumnIndex < 0) {
int64_t timestamp = curTsBlock_->getTimeByIndex(tsBlockIndex_);
return std::to_string(timestamp);
}
if (isNull(tsBlockColumnIndex, tsBlockIndex_)) {
lastReadWasNull_ = true;
- return "";
+ return boost::none;
}
lastReadWasNull_ = false;
return getStringByTsBlockColumnIndexAndDataType(tsBlockColumnIndex,
@@ -470,22 +473,25 @@ int64_t IoTDBRpcDataSet::getTimestamp(const std::string&
columnName) {
}
int64_t IoTDBRpcDataSet::getTimestampByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
- return getLongByTsBlockColumnIndex(tsBlockColumnIndex);
+ return getLongByTsBlockColumnIndex(tsBlockColumnIndex).value();
}
-boost::gregorian::date IoTDBRpcDataSet::getDateByIndex(int32_t columnIndex) {
+boost::optional<boost::gregorian::date>
IoTDBRpcDataSet::getDateByIndex(int32_t columnIndex) {
int32_t index = getTsBlockColumnIndexForColumnIndex(columnIndex);
return getDateByTsBlockColumnIndex(index);
}
-boost::gregorian::date IoTDBRpcDataSet::getDate(const std::string& columnName)
{
+boost::optional<boost::gregorian::date> IoTDBRpcDataSet::getDate(const
std::string& columnName) {
int32_t index = getTsBlockColumnIndexForColumnName(columnName);
return getDateByTsBlockColumnIndex(index);
}
-boost::gregorian::date IoTDBRpcDataSet::getDateByTsBlockColumnIndex(int32_t
tsBlockColumnIndex) {
- int32_t value = getIntByTsBlockColumnIndex(tsBlockColumnIndex);
- return parseIntToDate(value);
+boost::optional<boost::gregorian::date>
IoTDBRpcDataSet::getDateByTsBlockColumnIndex(int32_t tsBlockColumnIndex) {
+ auto value = getIntByTsBlockColumnIndex(tsBlockColumnIndex);
+ if (!value.is_initialized()) {
+ return boost::none;
+ }
+ return parseIntToDate(value.value());
}
TSDataType::TSDataType IoTDBRpcDataSet::getDataTypeByIndex(int32_t
columnIndex) {
diff --git a/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.h
b/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.h
index 96e5fd4b7ab..e3b591bb90d 100644
--- a/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.h
+++ b/iotdb-client/client-cpp/src/main/IoTDBRpcDataSet.h
@@ -69,24 +69,24 @@ public:
bool isNull(int32_t index, int32_t rowNum);
bool isNullByIndex(int32_t columnIndex);
bool isNullByColumnName(const std::string& columnName);
- bool getBooleanByIndex(int32_t columnIndex);
- bool getBoolean(const std::string& columnName);
- double getDoubleByIndex(int32_t columnIndex);
- double getDouble(const std::string& columnName);
- float getFloatByIndex(int32_t columnIndex);
- float getFloat(const std::string& columnName);
- int32_t getIntByIndex(int32_t columnIndex);
- int32_t getInt(const std::string& columnName);
- int64_t getLongByIndex(int32_t columnIndex);
- int64_t getLong(const std::string& columnName);
+ boost::optional<bool> getBooleanByIndex(int32_t columnIndex);
+ boost::optional<bool> getBoolean(const std::string& columnName);
+ boost::optional<double> getDoubleByIndex(int32_t columnIndex);
+ boost::optional<double> getDouble(const std::string& columnName);
+ boost::optional<float> getFloatByIndex(int32_t columnIndex);
+ boost::optional<float> getFloat(const std::string& columnName);
+ boost::optional<int32_t> getIntByIndex(int32_t columnIndex);
+ boost::optional<int32_t> getInt(const std::string& columnName);
+ boost::optional<int64_t> getLongByIndex(int32_t columnIndex);
+ boost::optional<int64_t> getLong(const std::string& columnName);
std::shared_ptr<Binary> getBinaryByIndex(int32_t columnIndex);
std::shared_ptr<Binary> getBinary(const std::string& columnName);
- std::string getStringByIndex(int32_t columnIndex);
- std::string getString(const std::string& columnName);
+ boost::optional<std::string> getStringByIndex(int32_t columnIndex);
+ boost::optional<std::string> getString(const std::string& columnName);
int64_t getTimestampByIndex(int32_t columnIndex);
int64_t getTimestamp(const std::string& columnName);
- boost::gregorian::date getDateByIndex(int32_t columnIndex);
- boost::gregorian::date getDate(const std::string& columnName);
+ boost::optional<boost::gregorian::date> getDateByIndex(int32_t
columnIndex);
+ boost::optional<boost::gregorian::date> getDate(const std::string&
columnName);
TSDataType::TSDataType getDataTypeByIndex(int32_t columnIndex);
TSDataType::TSDataType getDataType(const std::string& columnName);
@@ -113,15 +113,15 @@ private:
int32_t getTsBlockColumnIndexForColumnIndex(int32_t columnIndex);
void checkRecord();
TSDataType::TSDataType getDataTypeByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
- bool getBooleanByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
+ boost::optional<bool> getBooleanByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
std::string getStringByTsBlockColumnIndexAndDataType(int32_t index,
TSDataType::TSDataType tsDataType);
- double getDoubleByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
- float getFloatByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
- int32_t getIntByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
- int64_t getLongByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
+ boost::optional<double> getDoubleByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
+ boost::optional<float> getFloatByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
+ boost::optional<int32_t> getIntByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
+ boost::optional<int64_t> getLongByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
std::shared_ptr<Binary> getBinaryByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
- std::string getStringByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
- boost::gregorian::date getDateByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
+ boost::optional<std::string> getStringByTsBlockColumnIndex(int32_t
tsBlockColumnIndex);
+ boost::optional<boost::gregorian::date>
getDateByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
int64_t getTimestampByTsBlockColumnIndex(int32_t tsBlockColumnIndex);
std::string sql_;
diff --git a/iotdb-client/client-cpp/src/main/NodesSupplier.cpp
b/iotdb-client/client-cpp/src/main/NodesSupplier.cpp
index 5f268f075a1..f9ee90f169a 100644
--- a/iotdb-client/client-cpp/src/main/NodesSupplier.cpp
+++ b/iotdb-client/client-cpp/src/main/NodesSupplier.cpp
@@ -176,10 +176,18 @@ std::vector<TEndPoint>
NodesSupplier::fetchLatestEndpoints() {
std::vector<TEndPoint> ret;
while (sessionDataSet->hasNext()) {
auto record = sessionDataSet->next();
- std::string ip = record->fields.at(columnAddrIdx).stringV;
- int32_t port = record->fields.at(columnPortIdx).intV;
- std::string status = record->fields.at(columnStatusIdx).stringV;
-
+ std::string ip;
+ int32_t port;
+ std::string status;
+ if (record->fields.at(columnAddrIdx).stringV.is_initialized()) {
+ ip = record->fields.at(columnAddrIdx).stringV.value();
+ }
+ if (record->fields.at(columnPortIdx).intV.is_initialized()) {
+ port = record->fields.at(columnPortIdx).intV.value();
+ }
+ if (record->fields.at(columnStatusIdx).stringV.is_initialized()) {
+ status = record->fields.at(columnStatusIdx).stringV.value();
+ }
if (ip == "0.0.0.0" || status == REMOVING_STATUS) {
log_warn("Skipping invalid node: " + ip + ":" +
to_string(port));
continue;
diff --git a/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
b/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
index 30e11fa1efb..048d5340916 100644
--- a/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
+++ b/iotdb-client/client-cpp/src/main/SessionDataSet.cpp
@@ -54,28 +54,56 @@ std::string RowRecord::toString() {
TSDataType::TSDataType dataType = fields[i].dataType;
switch (dataType) {
case TSDataType::BOOLEAN:
- ret.append(fields[i].boolV ? "true" : "false");
+ if (!fields[i].boolV.is_initialized()) {
+ ret.append("null");
+ } else {
+ ret.append(fields[i].boolV.value() ? "true" : "false");
+ }
break;
case TSDataType::INT32:
- ret.append(std::to_string(fields[i].intV));
+ if (!fields[i].intV.is_initialized()) {
+ ret.append("null");
+ } else {
+ ret.append(std::to_string(fields[i].intV.value()));
+ }
break;
case TSDataType::DATE:
-
ret.append(boost::gregorian::to_iso_extended_string(fields[i].dateV));
+ if (!fields[i].dateV.is_initialized()) {
+ ret.append("null");
+ } else {
+
ret.append(boost::gregorian::to_iso_extended_string(fields[i].dateV.value()));
+ }
break;
case TSDataType::TIMESTAMP:
case TSDataType::INT64:
- ret.append(std::to_string(fields[i].longV));
+ if (!fields[i].longV.is_initialized()) {
+ ret.append("null");
+ } else {
+ ret.append(std::to_string(fields[i].longV.value()));
+ }
break;
case TSDataType::FLOAT:
- ret.append(std::to_string(fields[i].floatV));
+ if (!fields[i].floatV.is_initialized()) {
+ ret.append("null");
+ } else {
+ ret.append(std::to_string(fields[i].floatV.value()));
+ }
break;
case TSDataType::DOUBLE:
- ret.append(std::to_string(fields[i].doubleV));
+ if (!fields[i].doubleV.is_initialized()) {
+ ret.append("null");
+ } else {
+ ret.append(std::to_string(fields[i].doubleV.value()));
+ }
break;
case TSDataType::BLOB:
case TSDataType::STRING:
case TSDataType::TEXT:
- ret.append(fields[i].stringV);
+ if (!fields[i].stringV.is_initialized()) {
+ ret.append("null");
+ } else {
+ ret.append(fields[i].stringV.value());
+ }
break;
default:
break;
@@ -133,67 +161,67 @@ bool SessionDataSet::DataIterator::isNullByIndex(int32_t
columnIndex) {
return iotdbRpcDataSet_->isNullByIndex(columnIndex);
}
-bool SessionDataSet::DataIterator::getBooleanByIndex(int32_t columnIndex) {
+boost::optional<bool> SessionDataSet::DataIterator::getBooleanByIndex(int32_t
columnIndex) {
return iotdbRpcDataSet_->getBooleanByIndex(columnIndex);
}
-bool SessionDataSet::DataIterator::getBoolean(const std::string& columnName) {
+boost::optional<bool> SessionDataSet::DataIterator::getBoolean(const
std::string& columnName) {
return iotdbRpcDataSet_->getBoolean(columnName);
}
-double SessionDataSet::DataIterator::getDoubleByIndex(int32_t columnIndex) {
+boost::optional<double> SessionDataSet::DataIterator::getDoubleByIndex(int32_t
columnIndex) {
return iotdbRpcDataSet_->getDoubleByIndex(columnIndex);
}
-double SessionDataSet::DataIterator::getDouble(const std::string& columnName) {
+boost::optional<double> SessionDataSet::DataIterator::getDouble(const
std::string& columnName) {
return iotdbRpcDataSet_->getDouble(columnName);
}
-float SessionDataSet::DataIterator::getFloatByIndex(int32_t columnIndex) {
+boost::optional<float> SessionDataSet::DataIterator::getFloatByIndex(int32_t
columnIndex) {
return iotdbRpcDataSet_->getFloatByIndex(columnIndex);
}
-float SessionDataSet::DataIterator::getFloat(const std::string& columnName) {
+boost::optional<float> SessionDataSet::DataIterator::getFloat(const
std::string& columnName) {
return iotdbRpcDataSet_->getFloat(columnName);
}
-int32_t SessionDataSet::DataIterator::getIntByIndex(int32_t columnIndex) {
+boost::optional<int32_t> SessionDataSet::DataIterator::getIntByIndex(int32_t
columnIndex) {
return iotdbRpcDataSet_->getIntByIndex(columnIndex);
}
-int32_t SessionDataSet::DataIterator::getInt(const std::string& columnName) {
+boost::optional<int32_t> SessionDataSet::DataIterator::getInt(const
std::string& columnName) {
return iotdbRpcDataSet_->getInt(columnName);
}
-int64_t SessionDataSet::DataIterator::getLongByIndex(int32_t columnIndex) {
+boost::optional<int64_t> SessionDataSet::DataIterator::getLongByIndex(int32_t
columnIndex) {
return iotdbRpcDataSet_->getLongByIndex(columnIndex);
}
-int64_t SessionDataSet::DataIterator::getLong(const std::string& columnName) {
+boost::optional<int64_t> SessionDataSet::DataIterator::getLong(const
std::string& columnName) {
return iotdbRpcDataSet_->getLong(columnName);
}
-std::string SessionDataSet::DataIterator::getStringByIndex(int32_t
columnIndex) {
+boost::optional<std::string>
SessionDataSet::DataIterator::getStringByIndex(int32_t columnIndex) {
return iotdbRpcDataSet_->getStringByIndex(columnIndex);
}
-std::string SessionDataSet::DataIterator::getString(const std::string&
columnName) {
+boost::optional<std::string> SessionDataSet::DataIterator::getString(const
std::string& columnName) {
return iotdbRpcDataSet_->getString(columnName);
}
-int64_t SessionDataSet::DataIterator::getTimestampByIndex(int32_t columnIndex)
{
+boost::optional<int64_t>
SessionDataSet::DataIterator::getTimestampByIndex(int32_t columnIndex) {
return iotdbRpcDataSet_->getTimestampByIndex(columnIndex);
}
-int64_t SessionDataSet::DataIterator::getTimestamp(const std::string&
columnName) {
+boost::optional<int64_t> SessionDataSet::DataIterator::getTimestamp(const
std::string& columnName) {
return iotdbRpcDataSet_->getTimestamp(columnName);
}
-boost::gregorian::date SessionDataSet::DataIterator::getDateByIndex(int32_t
columnIndex) {
+boost::optional<boost::gregorian::date>
SessionDataSet::DataIterator::getDateByIndex(int32_t columnIndex) {
return iotdbRpcDataSet_->getDateByIndex(columnIndex);
}
-boost::gregorian::date SessionDataSet::DataIterator::getDate(const
std::string& columnName) {
+boost::optional<boost::gregorian::date>
SessionDataSet::DataIterator::getDate(const std::string& columnName) {
return iotdbRpcDataSet_->getDate(columnName);
}
@@ -225,7 +253,7 @@ shared_ptr<RowRecord>
SessionDataSet::constructRowRecordFromValueArray() {
field.intV = iotdbRpcDataSet_->getInt(columnName);
break;
case TSDataType::DATE:
- field.dateV =
parseIntToDate(iotdbRpcDataSet_->getInt(columnName));
+ field.dateV = iotdbRpcDataSet_->getDate(columnName);
break;
case TSDataType::INT64:
case TSDataType::TIMESTAMP:
@@ -243,7 +271,7 @@ shared_ptr<RowRecord>
SessionDataSet::constructRowRecordFromValueArray() {
field.stringV =
iotdbRpcDataSet_->getBinary(columnName)->getStringValue();
break;
default:
- throw new UnSupportedDataTypeException("Data type %s is not
supported." + dataType);
+ throw UnSupportedDataTypeException("Data type %s is not
supported." + dataType);
}
}
outFields.emplace_back(field);
diff --git a/iotdb-client/client-cpp/src/main/SessionDataSet.h
b/iotdb-client/client-cpp/src/main/SessionDataSet.h
index 0b8e4566604..c796c5758e7 100644
--- a/iotdb-client/client-cpp/src/main/SessionDataSet.h
+++ b/iotdb-client/client-cpp/src/main/SessionDataSet.h
@@ -104,29 +104,29 @@ public:
bool isNull(const std::string& columnName);
bool isNullByIndex(int32_t columnIndex);
- bool getBooleanByIndex(int32_t columnIndex);
- bool getBoolean(const std::string& columnName);
+ boost::optional<bool> getBooleanByIndex(int32_t columnIndex);
+ boost::optional<bool> getBoolean(const std::string& columnName);
- double getDoubleByIndex(int32_t columnIndex);
- double getDouble(const std::string& columnName);
+ boost::optional<double> getDoubleByIndex(int32_t columnIndex);
+ boost::optional<double> getDouble(const std::string& columnName);
- float getFloatByIndex(int32_t columnIndex);
- float getFloat(const std::string& columnName);
+ boost::optional<float> getFloatByIndex(int32_t columnIndex);
+ boost::optional<float> getFloat(const std::string& columnName);
- int32_t getIntByIndex(int32_t columnIndex);
- int32_t getInt(const std::string& columnName);
+ boost::optional<int32_t> getIntByIndex(int32_t columnIndex);
+ boost::optional<int32_t> getInt(const std::string& columnName);
- int64_t getLongByIndex(int32_t columnIndex);
- int64_t getLong(const std::string& columnName);
+ boost::optional<int64_t> getLongByIndex(int32_t columnIndex);
+ boost::optional<int64_t> getLong(const std::string& columnName);
- std::string getStringByIndex(int32_t columnIndex);
- std::string getString(const std::string& columnName);
+ boost::optional<std::string> getStringByIndex(int32_t columnIndex);
+ boost::optional<std::string> getString(const std::string& columnName);
- int64_t getTimestampByIndex(int32_t columnIndex);
- int64_t getTimestamp(const std::string& columnName);
+ boost::optional<int64_t> getTimestampByIndex(int32_t columnIndex);
+ boost::optional<int64_t> getTimestamp(const std::string& columnName);
- boost::gregorian::date getDateByIndex(int32_t columnIndex);
- boost::gregorian::date getDate(const std::string& columnName);
+ boost::optional<boost::gregorian::date> getDateByIndex(int32_t
columnIndex);
+ boost::optional<boost::gregorian::date> getDate(const std::string&
columnName);
int32_t findColumn(const std::string& columnName);
const std::vector<std::string>& getColumnNames() const;
diff --git a/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
b/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
index 803e7f583e2..bf2c7521769 100644
--- a/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
+++ b/iotdb-client/client-cpp/src/test/cpp/sessionIT.cpp
@@ -92,7 +92,7 @@ TEST_CASE("Test insertRecord by string",
"[testInsertRecord]") {
long index = 1;
count++;
for (const Field &f: sessionDataSet->next()->fields) {
- REQUIRE(f.longV == index);
+ REQUIRE(f.longV.value() == index);
index++;
}
}
@@ -137,7 +137,7 @@ TEST_CASE("Test insertRecords ", "[testInsertRecords]") {
long index = 1;
count++;
for (const Field &f: sessionDataSet->next()->fields) {
- REQUIRE(f.longV == index);
+ REQUIRE(f.longV.value() == index);
index++;
}
}
@@ -211,10 +211,10 @@ TEST_CASE("Test insertRecord with new datatypes ",
"[testTypedInsertRecordNewDat
for (int i = 0; i < 4; i++) {
REQUIRE(types[i] == record->fields[i].dataType);
}
- REQUIRE(record->fields[0].longV == value1);
- REQUIRE(record->fields[1].dateV == value2);
- REQUIRE(record->fields[2].stringV == value3);
- REQUIRE(record->fields[3].stringV == value4);
+ REQUIRE(record->fields[0].longV.value() == value1);
+ REQUIRE(record->fields[1].dateV.value() == value2);
+ REQUIRE(record->fields[2].stringV.value() == value3);
+ REQUIRE(record->fields[3].stringV.value() == value4);
count++;
}
REQUIRE(count == 100);
@@ -337,7 +337,7 @@ TEST_CASE("Test insertTablet ", "[testInsertTablet]") {
long index = 0;
count++;
for (const Field& f: sessionDataSet->next()->fields) {
- REQUIRE(f.longV == index);
+ REQUIRE(f.longV.value() == index);
index++;
}
}
@@ -387,14 +387,14 @@ TEST_CASE("Test insertTablets ", "[testInsertTablets]") {
long index = 0;
count++;
for (const Field& f: sessionDataSet->next()->fields) {
- REQUIRE(f.longV == index);
+ REQUIRE(f.longV.value() == index);
index++;
}
}
REQUIRE(count == 100);
}
-TEST_CASE("Test insertTablet new datatype", "[testInsertTabletNewDatatype]") {
+TEST_CASE("Test insertTablet multi datatype",
"[testInsertTabletMultiDatatype]") {
CaseReporter cr("testInsertTabletNewDatatype");
string deviceId = "root.test.d2";
vector<pair<string, TSDataType::TSDataType>> schemaList;
@@ -437,18 +437,14 @@ TEST_CASE("Test insertTablet new datatype",
"[testInsertTabletNewDatatype]") {
tablet.reset();
}
unique_ptr<SessionDataSet> sessionDataSet =
session->executeQueryStatement("select s1,s2,s3,s4 from root.test.d2");
+ auto dataIter = sessionDataSet->getIterator();
sessionDataSet->setFetchSize(1024);
int count = 0;
- while (sessionDataSet->hasNext()) {
- auto record = sessionDataSet->next();
- REQUIRE(record->fields.size() == 4);
- for (int i = 0; i < 4; i++) {
- REQUIRE(dataTypes[i] == record->fields[i].dataType);
- }
- REQUIRE(record->fields[0].longV == s1Value);
- REQUIRE(record->fields[1].dateV == s2Value);
- REQUIRE(record->fields[2].stringV == s3Value);
- REQUIRE(record->fields[3].stringV == s4Value);
+ while (dataIter.next()) {
+ REQUIRE(dataIter.getLongByIndex(2).value() == s1Value);
+ REQUIRE(dataIter.getDateByIndex(3).value() == s2Value);
+ REQUIRE(dataIter.getStringByIndex(4).value() == s3Value);
+ REQUIRE(dataIter.getStringByIndex(5).value() == s4Value);
count++;
}
REQUIRE(count == 100);
@@ -472,8 +468,8 @@ TEST_CASE("Test Last query ", "[testLastQuery]") {
long index = 0;
while (sessionDataSet->hasNext()) {
vector<Field> fields = sessionDataSet->next()->fields;
- REQUIRE("1" <= fields[1].stringV);
- REQUIRE(fields[1].stringV <= "3");
+ REQUIRE("1" <= fields[1].stringV.value());
+ REQUIRE(fields[1].stringV.value() <= "3");
index++;
}
}
@@ -509,9 +505,9 @@ TEST_CASE("Test Huge query ", "[testHugeQuery]") {
while (sessionDataSet->hasNext()) {
auto rowRecord = sessionDataSet->next();
REQUIRE(rowRecord->timestamp == count);
- REQUIRE(rowRecord->fields[0].longV== 1);
- REQUIRE(rowRecord->fields[1].longV == 2);
- REQUIRE(rowRecord->fields[2].longV == 3);
+ REQUIRE(rowRecord->fields[0].longV.value() == 1);
+ REQUIRE(rowRecord->fields[1].longV.value() == 2);
+ REQUIRE(rowRecord->fields[2].longV.value() == 3);
count++;
if (count % 1000 == 0) {
std::cout << count << "\t" << std::flush;
@@ -585,11 +581,11 @@ TEST_CASE("Test executeRawDataQuery ",
"[executeRawDataQuery]") {
vector<Field> fields = rowRecordPtr->fields;
REQUIRE(rowRecordPtr->timestamp == ts);
REQUIRE(fields[0].dataType == TSDataType::INT64);
- REQUIRE(fields[0].longV == ts);
+ REQUIRE(fields[0].longV.value() == ts);
REQUIRE(fields[1].dataType == TSDataType::INT64);
- REQUIRE(fields[1].longV == ts * 2);
+ REQUIRE(fields[1].longV.value() == ts * 2);
REQUIRE(fields[2].dataType == TSDataType::INT64);
- REQUIRE(fields[2].longV == ts *3);
+ REQUIRE(fields[2].longV.value() == ts *3);
ts++;
}
@@ -617,10 +613,10 @@ TEST_CASE("Test executeRawDataQuery ",
"[executeRawDataQuery]") {
vector<Field> fields = rowRecordPtr->fields;
REQUIRE(rowRecordPtr->timestamp == ts);
REQUIRE(fields[0].dataType == TSDataType::INT64);
- REQUIRE(fields[0].longV == 9);
+ REQUIRE(fields[0].longV.value() == 9);
REQUIRE(fields[1].dataType == TSDataType::UNKNOWN);
REQUIRE(fields[2].dataType == TSDataType::INT64);
- REQUIRE(fields[2].longV == 999);
+ REQUIRE(fields[2].longV.value() == 999);
}
//== Test executeRawDataQuery() with empty data
@@ -686,9 +682,9 @@ TEST_CASE("Test executeLastDataQuery ",
"[testExecuteLastDataQuery]") {
vector<Field> fields = rowRecordPtr->fields;
REQUIRE(rowRecordPtr->timestamp == tsCheck[index]);
- REQUIRE(fields[0].stringV == paths[index]);
- REQUIRE(fields[1].stringV == valueCheck[index]);
- REQUIRE(fields[2].stringV == "INT64");
+ REQUIRE(fields[0].stringV.value() == paths[index]);
+ REQUIRE(fields[1].stringV.value() == valueCheck[index]);
+ REQUIRE(fields[2].stringV.value() == "INT64");
index++;
}
@@ -708,9 +704,9 @@ TEST_CASE("Test executeLastDataQuery ",
"[testExecuteLastDataQuery]") {
vector<Field> fields = rowRecordPtr->fields;
REQUIRE(rowRecordPtr->timestamp == tsCheck[index]);
- REQUIRE(fields[0].stringV == paths[index]);
- REQUIRE(fields[1].stringV == valueCheck[index]);
- REQUIRE(fields[2].stringV == "INT64");
+ REQUIRE(fields[0].stringV.value() == paths[index]);
+ REQUIRE(fields[1].stringV.value() == valueCheck[index]);
+ REQUIRE(fields[2].stringV.value() == "INT64");
index++;
}
diff --git a/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
b/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
index 420c2c441bc..3534abd46f8 100644
--- a/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
+++ b/iotdb-client/client-cpp/src/test/cpp/sessionRelationalIT.cpp
@@ -59,7 +59,7 @@ TEST_CASE("Create table success", "[createTable]") {
sessionDataSet->setFetchSize(1024);
bool tableExist = false;
while (sessionDataSet->hasNext()) {
- if (sessionDataSet->next()->fields[0].stringV == "table0") {
+ if (sessionDataSet->next()->fields[0].stringV.value() == "table0") {
tableExist = true;
break;
}
@@ -112,9 +112,9 @@ TEST_CASE("Test insertRelationalTablet",
"[testInsertRelationalTablet]") {
unique_ptr<SessionDataSet> sessionDataSet =
session->executeQueryStatement("SELECT * FROM table1 order by time");
while (sessionDataSet->hasNext()) {
auto rowRecord = sessionDataSet->next();
- REQUIRE(rowRecord->fields[1].stringV == string("tag:") +
to_string(cnt));
- REQUIRE(rowRecord->fields[2].stringV == string("attr:") +
to_string(cnt));
- REQUIRE(fabs(rowRecord->fields[3].doubleV - cnt * 1.1) < 0.0001);
+ REQUIRE(rowRecord->fields[1].stringV.value() == string("tag:") +
to_string(cnt));
+ REQUIRE(rowRecord->fields[2].stringV.value() == string("attr:") +
to_string(cnt));
+ REQUIRE(fabs(rowRecord->fields[3].doubleV.value() - cnt * 1.1) <
0.0001);
cnt++;
}
REQUIRE(cnt == 15);
@@ -169,6 +169,12 @@ TEST_CASE("Test RelationalTabletTsblockRead",
"[testRelationalTabletTsblockRead]
tablet.addValue(8, rowIndex, "blob_" + to_string(row));
tablet.addValue(9, rowIndex, "string_" + to_string(row));
+ if (row % 2 == 0) {
+ for (int col = 0; col <= 9; col++) {
+ tablet.bitMaps[col].mark(row);
+ }
+ }
+
if (tablet.rowSize == tablet.maxRowNumber) {
session->insert(tablet, true);
tablet.reset();
@@ -186,17 +192,62 @@ TEST_CASE("Test RelationalTabletTsblockRead",
"[testRelationalTabletTsblockRead]
int rowNum = 0;
timestamp = 0;
while (dataIter.next()) {
- REQUIRE(dataIter.getLongByIndex(1) == timestamp + rowNum);
- REQUIRE(dataIter.getBooleanByIndex(2) == (rowNum % 2 == 0));
- REQUIRE(dataIter.getIntByIndex(3) == static_cast<int32_t>(rowNum));
- REQUIRE(dataIter.getLongByIndex(4) == static_cast<int64_t>(timestamp));
- REQUIRE(fabs(dataIter.getFloatByIndex(5) - rowNum * 1.1f) < 0.1f);
- REQUIRE(fabs(dataIter.getDoubleByIndex(6) - rowNum * 1.1f) < 0.1);
- REQUIRE(dataIter.getStringByIndex(7) == "text_" + to_string(rowNum));
- REQUIRE(dataIter.getLongByIndex(8) == static_cast<int64_t>(timestamp));
- REQUIRE(dataIter.getDateByIndex(9) == boost::gregorian::date(2025, 5,
15));
- REQUIRE(dataIter.getStringByIndex(10) == "blob_" + to_string(rowNum));
- REQUIRE(dataIter.getStringByIndex(11) == "string_" +
to_string(rowNum));
+ if (rowNum % 2 == 0) {
+ REQUIRE_FALSE(dataIter.getBooleanByIndex(2).is_initialized());
+ REQUIRE_FALSE(dataIter.getIntByIndex(3).is_initialized());
+ REQUIRE_FALSE(dataIter.getLongByIndex(4).is_initialized());
+ REQUIRE_FALSE(dataIter.getFloatByIndex(5).is_initialized());
+ REQUIRE_FALSE(dataIter.getDoubleByIndex(6).is_initialized());
+ REQUIRE_FALSE(dataIter.getStringByIndex(7).is_initialized());
+ REQUIRE_FALSE(dataIter.getLongByIndex(8).is_initialized());
+ REQUIRE_FALSE(dataIter.getDateByIndex(9).is_initialized());
+ REQUIRE_FALSE(dataIter.getStringByIndex(10).is_initialized());
+ REQUIRE_FALSE(dataIter.getStringByIndex(11).is_initialized());
+ } else {
+ REQUIRE(dataIter.getLongByIndex(1).value() == timestamp + rowNum);
+ REQUIRE(dataIter.getBooleanByIndex(2).value() == (rowNum % 2 ==
0));
+ REQUIRE(dataIter.getIntByIndex(3).value() ==
static_cast<int32_t>(rowNum));
+ REQUIRE(dataIter.getLongByIndex(4).value() ==
static_cast<int64_t>(timestamp));
+ REQUIRE(fabs(dataIter.getFloatByIndex(5).value() - rowNum * 1.1f)
< 0.1f);
+ REQUIRE(fabs(dataIter.getDoubleByIndex(6).value() - rowNum * 1.1f)
< 0.1);
+ REQUIRE(dataIter.getStringByIndex(7).value() == "text_" +
to_string(rowNum));
+ REQUIRE(dataIter.getLongByIndex(8).value() ==
static_cast<int64_t>(timestamp));
+ 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));
+ }
+ rowNum++;
+ }
+ REQUIRE(rowNum == maxRowNumber);
+
+ sessionDataSet = session->executeQueryStatement("SELECT * FROM table1
order by time");
+ rowNum = 0;
+ timestamp = 0;
+ while (sessionDataSet->hasNext()) {
+ auto record = sessionDataSet->next();
+ if (rowNum % 2 == 0) {
+ REQUIRE_FALSE(record->fields[1].boolV.is_initialized());
+ REQUIRE_FALSE(record->fields[2].intV.is_initialized());
+ REQUIRE_FALSE(record->fields[3].longV.is_initialized());
+ REQUIRE_FALSE(record->fields[4].floatV.is_initialized());
+ REQUIRE_FALSE(record->fields[5].doubleV.is_initialized());
+ REQUIRE_FALSE(record->fields[6].stringV.is_initialized());
+ REQUIRE_FALSE(record->fields[7].longV.is_initialized());
+ REQUIRE_FALSE(record->fields[8].dateV.is_initialized());
+ REQUIRE_FALSE(record->fields[9].stringV.is_initialized());
+ REQUIRE_FALSE(record->fields[10].stringV.is_initialized());
+ } else {
+ REQUIRE(record->fields[1].boolV.value() == (rowNum % 2 == 0));
+ REQUIRE(record->fields[2].intV.value() ==
static_cast<int32_t>(rowNum));
+ REQUIRE(record->fields[3].longV.value() ==
static_cast<int64_t>(timestamp));
+ REQUIRE(fabs(record->fields[4].floatV.value() - rowNum * 1.1f) <
0.1f);
+ REQUIRE(fabs(record->fields[5].doubleV.value() - rowNum * 1.1f) <
0.1);
+ REQUIRE(record->fields[6].stringV.value() == "text_" +
to_string(rowNum));
+ REQUIRE(record->fields[7].longV.value() ==
static_cast<int64_t>(timestamp));
+ REQUIRE(record->fields[8].dateV.value() ==
boost::gregorian::date(2025, 5, 15));
+ REQUIRE(record->fields[9].stringV.value() == "blob_" +
to_string(rowNum));
+ REQUIRE(record->fields[10].stringV.value() == "string_" +
to_string(rowNum));
+ }
rowNum++;
}
REQUIRE(rowNum == maxRowNumber);