Skip to content

Commit 6b9b6a2

Browse files
committed
First cut at implementing float8array serializer
1 parent 78387ad commit 6b9b6a2

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

src/oatpp-postgresql/mapping/Deserializer.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -339,19 +339,18 @@ oatpp::Void Deserializer::deserializeArray(const Deserializer* _this, const InDa
339339

340340
// everything is in network order!!!
341341
// only handle 1d array for now
342-
if (ntohl(pgArray->ndim) > 1) {
342+
if (ntohl(pgArray->header.ndim) > 1) {
343343
throw std::runtime_error("[oatpp::postgresql::mapping::Deserializer::deserializeArray()]: Dimension > 1");
344344
}
345345

346346
// make sure data is the right type
347-
if (ntohl(pgArray->oid) == FLOAT8OID) {
347+
if (ntohl(pgArray->header.oid) == FLOAT8OID) {
348348
// build the array
349349
auto vec = oatpp::Vector<Float64>::createShared();
350-
auto pElem = &pgArray->elem;
351-
auto nElem = ntohl(*pElem);
350+
auto nElem = ntohl(pgArray->header.size);
352351
for (int i = 0; i < nElem; i++) {
353352
// get element size, point to element data
354-
auto elemSize = ntohl(*pElem++);
353+
auto elemSize = ntohl(pgArray->elem[i].size);
355354
// quit if we get an empty element
356355
if (elemSize == 0) {
357356
break;
@@ -363,8 +362,8 @@ oatpp::Void Deserializer::deserializeArray(const Deserializer* _this, const InDa
363362
}
364363
// get the 64 bit host order data, pointing to next element
365364
// TODO: make sure this matches element size
366-
v_int64 l1 = ntohl(*pElem++);
367-
v_int64 l2 = ntohl(*pElem++);
365+
v_int64 l1 = ntohl(pgArray->elem[i].value[0]);
366+
v_int64 l2 = ntohl(pgArray->elem[i].value[1]);
368367
v_int64 intVal = (l1 << 32) | l2 ;
369368
v_float64 val = *reinterpret_cast<p_float64>(&intVal);
370369
vec->push_back(val);

src/oatpp-postgresql/mapping/PgArray.hpp

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,26 @@
55
#ifndef oatpp_postgresql_mapping_PgArray_hpp
66
#define oatpp_postgresql_mapping_PgArray_hpp
77

8+
// TODO: Assumes 64 bits for each element -- only valid for float64 and int64!
9+
struct PgElem {
10+
v_int32 size;
11+
v_int32 value[2];
12+
};
13+
814
// after https://stackoverflow.com/questions/4016412/postgresqls-libpq-encoding-for-binary-transport-of-array-data
9-
struct PgArray {
10-
int32_t ndim; // Number of dimensions
11-
int32_t _ign; // offset for data, removed by libpq
15+
struct PgArrayHeader {
16+
v_int32 ndim; // Number of dimensions
17+
v_int32 _ign; // offset for data, removed by libpq
1218
Oid oid; // type of element in the array
1319

1420
// Start of array (1st dimension)
15-
int32_t size; // Number of elements
16-
int32_t index; // Index of first element
17-
int32_t elem; // Beginning of (size, value) elements
21+
v_int32 size; // Number of elements
22+
v_int32 index; // Index of first element
23+
};
24+
25+
struct PgArray {
26+
PgArrayHeader header;
27+
PgElem elem[1]; // Beginning of (size, value) elements
1828
};
1929

2030
#endif // oatpp_postgresql_mapping_PgArray_hpp

src/oatpp-postgresql/mapping/Serializer.cpp

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "Serializer.hpp"
2626

2727
#include "Oid.hpp"
28+
#include "PgArray.hpp"
2829
#include "oatpp-postgresql/Types.hpp"
2930

3031
#if defined(WIN32) || defined(_WIN32)
@@ -397,10 +398,33 @@ void Serializer::serializeArray(const Serializer* _this, OutputData& outData, co
397398

398399
if(polymorph) {
399400
auto v = polymorph.staticCast<oatpp::Vector<Float64>>();
400-
outData.data = nullptr;
401-
outData.dataSize = 0;
401+
402+
// get size of header + vector size * sizeof each element (size + data)
403+
auto dataSize = sizeof(PgArrayHeader) + v->size() * sizeof(PgElem);
404+
outData.dataBuffer.reset(new char[dataSize]);
405+
outData.dataSize = dataSize;
402406
outData.dataFormat = 1;
403407
outData.oid = FLOAT8ARRAYOID;
408+
outData.data = outData.dataBuffer.get();
409+
auto buffer = outData.data;
410+
411+
// load the data in to the pgArray
412+
auto *pgArray = reinterpret_cast<PgArray *>(buffer);
413+
// only support 1d float8 arrays for now
414+
pgArray->header.ndim = htonl(1);
415+
pgArray->header._ign = 0;
416+
pgArray->header.oid = htonl(FLOAT8OID);
417+
pgArray->header.size = htonl(v->size());
418+
pgArray->header.index = 0;
419+
420+
// stuff in the elements in network order
421+
for (int i=0; i < v->size(); i++) {
422+
pgArray->elem[i].size = htonl(sizeof(v_float64));
423+
v_float64 fValue = v->at(i);
424+
auto pVal = reinterpret_cast<p_int64>(&fValue);
425+
pgArray->elem[i].value[0] = htonl(*pVal >> 32);
426+
pgArray->elem[i].value[1] = htonl(*pVal & 0xFFFFFFFF);
427+
}
404428
} else{
405429
serNull(outData);
406430
}

0 commit comments

Comments
 (0)