Skip to content

Commit 3767282

Browse files
authored
feat(client-cpp): add SessionC DATE/BLOB support and RowRecord getters (#17956)
* feat(client-cpp): add SessionC DATE/BLOB support and RowRecord getters Introduce TSDate_C for typed DATE inserts, ts_row_record_get_date_int32 and ts_row_record_get_string_byte_length, and expand c_rowDelete IT to cover DATE/BLOB readback and deletion paths. * test(client-cpp): cover TEXT and STRING in c_rowDelete IT Add TS_TYPE_STRING readback assertions alongside explicit TEXT checks in the RowRecord integration test. * chore(client-cpp): remove redundant TSDate_C comment
1 parent 5e6f1c2 commit 3767282

3 files changed

Lines changed: 79 additions & 8 deletions

File tree

iotdb-client/client-cpp/src/include/SessionC.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ typedef enum {
105105

106106
typedef enum { TS_COL_TAG = 0, TS_COL_FIELD = 1, TS_COL_ATTRIBUTE = 2 } TSColumnCategory_C;
107107

108+
typedef struct {
109+
int year;
110+
int month;
111+
int day;
112+
} TSDate_C;
113+
108114
/* ============================================================
109115
* Session Lifecycle — Tree Model
110116
* ============================================================ */
@@ -382,6 +388,12 @@ double ts_row_record_get_double(CRowRecord* record, int index);
382388

383389
const char* ts_row_record_get_string(CRowRecord* record, int index);
384390

391+
/** Returns YYYYMMDD for DATE fields; 0 if record is null, index is out of range, field is null, or not DATE. */
392+
int32_t ts_row_record_get_date_int32(CRowRecord* record, int index);
393+
394+
/** Byte length of the string/binary field (TEXT, BLOB, STRING, OBJECT, ...); 0 if null or out of range. */
395+
size_t ts_row_record_get_string_byte_length(CRowRecord* record, int index);
396+
385397
/** Returns TS_TYPE_INVALID if record is null or index is out of range. */
386398
TSDataType_C ts_row_record_get_data_type(CRowRecord* record, int index);
387399

iotdb-client/client-cpp/src/session/SessionC.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919

2020
#include "SessionC.h"
21+
#include "Date.h"
2122
#include "Session.h"
2223
#include "TableSession.h"
2324
#include "TableSessionBuilder.h"
@@ -184,6 +185,12 @@ static std::vector<char*> toCharPtrVec(const TSDataType_C* types, const void* co
184185
result[i] = reinterpret_cast<char*>(p);
185186
break;
186187
}
188+
case TS_TYPE_DATE: {
189+
const TSDate_C* src = static_cast<const TSDate_C*>(values[i]);
190+
IoTDBDate* p = new IoTDBDate(src->year, src->month, src->day);
191+
result[i] = reinterpret_cast<char*>(p);
192+
break;
193+
}
187194
case TS_TYPE_TEXT:
188195
case TS_TYPE_STRING:
189196
case TS_TYPE_BLOB:
@@ -219,6 +226,9 @@ static void freeCharPtrVec(std::vector<char*>& vec, const TSDataType_C* types, i
219226
case TS_TYPE_DOUBLE:
220227
delete reinterpret_cast<double*>(vec[i]);
221228
break;
229+
case TS_TYPE_DATE:
230+
delete reinterpret_cast<IoTDBDate*>(vec[i]);
231+
break;
222232
default:
223233
delete[] vec[i];
224234
break;
@@ -1471,6 +1481,29 @@ const char* ts_row_record_get_string(CRowRecord* record, int index) {
14711481
return "";
14721482
}
14731483

1484+
int32_t ts_row_record_get_date_int32(CRowRecord* record, int index) {
1485+
if (!record || !record->cpp)
1486+
return 0;
1487+
if (index < 0 || index >= (int)record->cpp->fields.size())
1488+
return 0;
1489+
const Field& f = record->cpp->fields[index];
1490+
if (f.dataType != TSDataType::DATE || !f.dateV.is_initialized())
1491+
return 0;
1492+
return parseDateExpressionToInt(f.dateV.value());
1493+
}
1494+
1495+
size_t ts_row_record_get_string_byte_length(CRowRecord* record, int index) {
1496+
if (!record || !record->cpp)
1497+
return 0;
1498+
if (index < 0 || index >= (int)record->cpp->fields.size())
1499+
return 0;
1500+
const Field& f = record->cpp->fields[index];
1501+
if (f.stringV.is_initialized()) {
1502+
return f.stringV.value().size();
1503+
}
1504+
return 0;
1505+
}
1506+
14741507
TSDataType_C ts_row_record_get_data_type(CRowRecord* record, int index) {
14751508
if (!record || !record->cpp)
14761509
return TS_TYPE_INVALID;

iotdb-client/client-cpp/test/cpp/sessionCIT.cpp

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,10 @@ TEST_CASE("C API - RowRecord and delete data APIs", "[c_rowDelete]") {
687687
const char* pf = "root.cov_types.d1.sf";
688688
const char* pd = "root.cov_types.d1.sd";
689689
const char* pt = "root.cov_types.d1.st";
690-
const char* tpaths[] = {pb, pi, pf, pd, pt};
690+
const char* pstr = "root.cov_types.d1.sstr";
691+
const char* pdate = "root.cov_types.d1.sdate";
692+
const char* pblob = "root.cov_types.d1.sblob";
693+
const char* tpaths[] = {pb, pi, pf, pd, pt, pstr, pdate, pblob};
691694
for (const char* tp : tpaths) {
692695
dropTimeseriesIfExists(g_session, tp);
693696
}
@@ -701,36 +704,56 @@ TEST_CASE("C API - RowRecord and delete data APIs", "[c_rowDelete]") {
701704
TS_COMPRESSION_SNAPPY) == TS_OK);
702705
REQUIRE(ts_session_create_timeseries(g_session, pt, TS_TYPE_TEXT, TS_ENCODING_PLAIN,
703706
TS_COMPRESSION_SNAPPY) == TS_OK);
707+
REQUIRE(ts_session_create_timeseries(g_session, pstr, TS_TYPE_STRING, TS_ENCODING_PLAIN,
708+
TS_COMPRESSION_SNAPPY) == TS_OK);
709+
REQUIRE(ts_session_create_timeseries(g_session, pdate, TS_TYPE_DATE, TS_ENCODING_PLAIN,
710+
TS_COMPRESSION_SNAPPY) == TS_OK);
711+
REQUIRE(ts_session_create_timeseries(g_session, pblob, TS_TYPE_BLOB, TS_ENCODING_PLAIN,
712+
TS_COMPRESSION_SNAPPY) == TS_OK);
704713

705714
const char* dev = "root.cov_types.d1";
706-
const char* names[] = {"sb", "si", "sf", "sd", "st"};
715+
const char* names[] = {"sb", "si", "sf", "sd", "st", "sstr", "sdate", "sblob"};
707716
TSDataType_C types[] = {TS_TYPE_BOOLEAN, TS_TYPE_INT32, TS_TYPE_FLOAT, TS_TYPE_DOUBLE,
708-
TS_TYPE_TEXT};
717+
TS_TYPE_TEXT, TS_TYPE_STRING, TS_TYPE_DATE, TS_TYPE_BLOB};
709718
bool bv = true;
710719
int32_t iv = 42;
711720
float fv = 2.5f;
712721
double dv = 3.25;
713722
const char* tv = "hi";
714-
const void* vals[] = {&bv, &iv, &fv, &dv, tv};
715-
REQUIRE(ts_session_insert_record(g_session, dev, 500LL, 5, names, types, vals) == TS_OK);
723+
const char* strVal = "hello";
724+
TSDate_C dateVal = {2025, 5, 7};
725+
const char* blobVal = "blobXY";
726+
const void* vals[] = {&bv, &iv, &fv, &dv, tv, strVal, &dateVal, blobVal};
727+
REQUIRE(ts_session_insert_record(g_session, dev, 500LL, 8, names, types, vals) == TS_OK);
716728

717729
CSessionDataSet* dataSet = nullptr;
718730
REQUIRE(ts_session_execute_query(g_session,
719-
"select sb,si,sf,sd,st from root.cov_types.d1 where time=500",
731+
"select sb,si,sf,sd,st,sstr,sdate,sblob from root.cov_types.d1 "
732+
"where time=500",
720733
&dataSet) == TS_OK);
721734
REQUIRE(dataSet != nullptr);
722735
REQUIRE(ts_dataset_has_next(dataSet));
723736
CRowRecord* record = ts_dataset_next(dataSet);
724737
REQUIRE(record != nullptr);
725738
REQUIRE(ts_row_record_get_timestamp(record) == 500LL);
726-
REQUIRE(ts_row_record_get_field_count(record) == 5);
739+
REQUIRE(ts_row_record_get_field_count(record) == 8);
727740
REQUIRE_FALSE(ts_row_record_is_null(record, 0));
728741
REQUIRE(ts_row_record_get_bool(record, 0) == true);
729742
REQUIRE(ts_row_record_get_int32(record, 1) == 42);
730743
REQUIRE(std::fabs(ts_row_record_get_float(record, 2) - 2.5f) < 1e-4f);
731744
REQUIRE(std::fabs(ts_row_record_get_double(record, 3) - 3.25) < 1e-9);
745+
REQUIRE(ts_row_record_get_data_type(record, 4) == TS_TYPE_TEXT);
732746
REQUIRE(std::string(ts_row_record_get_string(record, 4)) == "hi");
733-
REQUIRE(ts_row_record_get_data_type(record, 0) == TS_TYPE_BOOLEAN);
747+
REQUIRE(ts_row_record_get_string_byte_length(record, 4) == 2);
748+
REQUIRE(ts_row_record_get_data_type(record, 5) == TS_TYPE_STRING);
749+
REQUIRE(std::string(ts_row_record_get_string(record, 5)) == "hello");
750+
REQUIRE(ts_row_record_get_string_byte_length(record, 5) == 5);
751+
REQUIRE(ts_row_record_get_date_int32(record, 6) == 20250507);
752+
REQUIRE(std::string(ts_row_record_get_string(record, 7)) == "blobXY");
753+
REQUIRE(ts_row_record_get_string_byte_length(record, 7) == 6);
754+
for (int i = 0; i < 8; i++) {
755+
REQUIRE(ts_row_record_get_data_type(record, i) == types[i]);
756+
}
734757
ts_row_record_destroy(record);
735758
ts_dataset_destroy(dataSet);
736759

@@ -743,5 +766,8 @@ TEST_CASE("C API - RowRecord and delete data APIs", "[c_rowDelete]") {
743766
REQUIRE(ts_session_delete_timeseries(g_session, pf) == TS_OK);
744767
REQUIRE(ts_session_delete_timeseries(g_session, pd) == TS_OK);
745768
REQUIRE(ts_session_delete_timeseries(g_session, pt) == TS_OK);
769+
REQUIRE(ts_session_delete_timeseries(g_session, pstr) == TS_OK);
770+
REQUIRE(ts_session_delete_timeseries(g_session, pdate) == TS_OK);
771+
REQUIRE(ts_session_delete_timeseries(g_session, pblob) == TS_OK);
746772
REQUIRE(ts_session_delete_database(g_session, sg) == TS_OK);
747773
}

0 commit comments

Comments
 (0)