diff --git a/iotdb-client/client-cpp/src/include/Column.h b/iotdb-client/client-cpp/src/include/Column.h index 8794e7b8d5e3..c278c6ebe738 100644 --- a/iotdb-client/client-cpp/src/include/Column.h +++ b/iotdb-client/client-cpp/src/include/Column.h @@ -196,6 +196,9 @@ class IntColumn : public Column { ColumnEncoding getEncoding() const override; int32_t getInt(int32_t position) const override; + int64_t getLong(int32_t position) const override; + float getFloat(int32_t position) const override; + double getDouble(int32_t position) const override; std::vector getInts() const override; bool mayHaveNull() const override; @@ -220,6 +223,7 @@ class FloatColumn : public Column { ColumnEncoding getEncoding() const override; float getFloat(int32_t position) const override; + double getDouble(int32_t position) const override; std::vector getFloats() const override; bool mayHaveNull() const override; @@ -244,6 +248,7 @@ class LongColumn : public Column { ColumnEncoding getEncoding() const override; int64_t getLong(int32_t position) const override; + double getDouble(int32_t position) const override; std::vector getLongs() const override; bool mayHaveNull() const override; diff --git a/iotdb-client/client-cpp/src/include/Common.h b/iotdb-client/client-cpp/src/include/Common.h index 49dca0bca4b1..f36b38206b8d 100644 --- a/iotdb-client/client-cpp/src/include/Common.h +++ b/iotdb-client/client-cpp/src/include/Common.h @@ -185,7 +185,7 @@ class Field { case TSDataType::BLOB: return !stringV.is_initialized(); case TSDataType::DATE: - return !dateV.is_initialized(); + return !dateV.is_initialized() || dateV.value().is_not_a_date(); default: return true; } diff --git a/iotdb-client/client-cpp/src/session/Column.cpp b/iotdb-client/client-cpp/src/session/Column.cpp index 203fcefd8d9a..906a78968ed2 100644 --- a/iotdb-client/client-cpp/src/session/Column.cpp +++ b/iotdb-client/client-cpp/src/session/Column.cpp @@ -152,6 +152,18 @@ int32_t IntColumn::getInt(int32_t position) const { return values_[position + arrayOffset_]; } +int64_t IntColumn::getLong(int32_t position) const { + return values_[position + arrayOffset_]; +} + +float IntColumn::getFloat(int32_t position) const { + return values_[position + arrayOffset_]; +} + +double IntColumn::getDouble(int32_t position) const { + return values_[position + arrayOffset_]; +} + std::vector IntColumn::getInts() const { return values_; } @@ -204,6 +216,10 @@ float FloatColumn::getFloat(int32_t position) const { return values_[position + arrayOffset_]; } +double FloatColumn::getDouble(int32_t position) const { + return values_[position + arrayOffset_]; +} + std::vector FloatColumn::getFloats() const { return values_; } @@ -256,6 +272,10 @@ int64_t LongColumn::getLong(int32_t position) const { return values_[position + arrayOffset_]; } +double LongColumn::getDouble(int32_t position) const { + return values_[position + arrayOffset_]; +} + std::vector LongColumn::getLongs() const { return values_; } diff --git a/iotdb-client/client-cpp/src/session/Date.cpp b/iotdb-client/client-cpp/src/session/Date.cpp index 91095c250dad..1e6f62edd1d2 100644 --- a/iotdb-client/client-cpp/src/session/Date.cpp +++ b/iotdb-client/client-cpp/src/session/Date.cpp @@ -53,9 +53,6 @@ int32_t parseDateExpressionToInt(const IoTDBDate& date) { } IoTDBDate parseIntToDate(int32_t dateInt) { - if (dateInt == EMPTY_DATE_INT) { - return IoTDBDate::notADate(); - } const int year = dateInt / 10000; const int month = (dateInt % 10000) / 100; const int day = dateInt % 100; diff --git a/iotdb-client/client-cpp/src/session/SessionC.cpp b/iotdb-client/client-cpp/src/session/SessionC.cpp index 7d86bd348f85..17948793e74b 100644 --- a/iotdb-client/client-cpp/src/session/SessionC.cpp +++ b/iotdb-client/client-cpp/src/session/SessionC.cpp @@ -1487,8 +1487,10 @@ int32_t ts_row_record_get_date_int32(CRowRecord* record, int index) { if (index < 0 || index >= (int)record->cpp->fields.size()) return 0; const Field& f = record->cpp->fields[index]; - if (f.dataType != TSDataType::DATE || !f.dateV.is_initialized()) + if (f.dataType != TSDataType::DATE || !f.dateV.is_initialized() || + f.dateV.value().is_not_a_date()) { return 0; + } return parseDateExpressionToInt(f.dateV.value()); } diff --git a/iotdb-client/client-cpp/test/cpp/sessionCIT.cpp b/iotdb-client/client-cpp/test/cpp/sessionCIT.cpp index b79dd1100e66..892a307082e8 100644 --- a/iotdb-client/client-cpp/test/cpp/sessionCIT.cpp +++ b/iotdb-client/client-cpp/test/cpp/sessionCIT.cpp @@ -771,3 +771,33 @@ TEST_CASE("C API - RowRecord and delete data APIs", "[c_rowDelete]") { REQUIRE(ts_session_delete_timeseries(g_session, pblob) == TS_OK); REQUIRE(ts_session_delete_database(g_session, sg) == TS_OK); } + +TEST_CASE("C API - Query DATE 1000-01-01", "[c_dateMinYear]") { + CaseReporter cr("c_dateMinYear"); + + const char* path = "root.ctest.d1.s_date_min"; + ensureTimeseries(g_session, path, TS_TYPE_DATE, TS_ENCODING_PLAIN, TS_COMPRESSION_SNAPPY); + + const char* deviceId = "root.ctest.d1"; + const char* measurements[] = {"s_date_min"}; + TSDataType_C types[] = {TS_TYPE_DATE}; + TSDate_C dateVal = {1000, 1, 1}; + const void* vals[] = {&dateVal}; + REQUIRE(ts_session_insert_record(g_session, deviceId, 1000LL, 1, measurements, types, vals) == + TS_OK); + + CSessionDataSet* dataSet = nullptr; + REQUIRE(ts_session_execute_query(g_session, + "select s_date_min from root.ctest.d1 where time=1000", + &dataSet) == TS_OK); + REQUIRE(dataSet != nullptr); + REQUIRE(ts_dataset_has_next(dataSet)); + CRowRecord* record = ts_dataset_next(dataSet); + REQUIRE(record != nullptr); + REQUIRE_FALSE(ts_row_record_is_null(record, 0)); + REQUIRE(ts_row_record_get_date_int32(record, 0) == 10000101); + ts_row_record_destroy(record); + ts_dataset_destroy(dataSet); + + REQUIRE(ts_session_delete_timeseries(g_session, path) == TS_OK); +} diff --git a/iotdb-client/client-cpp/test/cpp/sessionIT.cpp b/iotdb-client/client-cpp/test/cpp/sessionIT.cpp index c0428f6e84a7..59c7c9449293 100644 --- a/iotdb-client/client-cpp/test/cpp/sessionIT.cpp +++ b/iotdb-client/client-cpp/test/cpp/sessionIT.cpp @@ -1037,3 +1037,31 @@ TEST_CASE("SessionPool getSession times out when exhausted", "[sessionPool]") { reused.release(); pool->close(); } + +TEST_CASE("Query DATE 1000-01-01", "[dateMinYear]") { + CaseReporter cr("dateMinYear"); + const string timeseries = "root.test.d1.s_date_min"; + if (session->checkTimeseriesExists(timeseries)) { + session->deleteTimeseries(timeseries); + } + session->createTimeseries(timeseries, TSDataType::DATE, TSEncoding::PLAIN, + CompressionType::SNAPPY); + + const string deviceId = "root.test.d1"; + const vector measurements = {"s_date_min"}; + const vector types = {TSDataType::DATE}; + const IoTDBDate dateValue(1000, 1, 1); + vector values = {const_cast(reinterpret_cast(&dateValue))}; + session->insertRecord(deviceId, 1000LL, measurements, types, values); + + unique_ptr sessionDataSet = + session->executeQueryStatement("select s_date_min from root.test.d1 where time=1000"); + REQUIRE(sessionDataSet->hasNext()); + auto record = sessionDataSet->next(); + REQUIRE(record->fields.size() == 1); + REQUIRE_FALSE(record->fields[0].isNull()); + REQUIRE(record->fields[0].dateV.value() == dateValue); + REQUIRE(record->fields[0].dateV.value().toIsoExtendedString() == "1000-01-01"); + + session->deleteTimeseries(timeseries); +}