@@ -279,6 +279,8 @@ const oatpp::Type* Deserializer::guessAnyType(Oid oid) {
279
279
280
280
case TIMESTAMPOID: return oatpp::UInt64::Class::getType ();
281
281
282
+ case FLOAT4ARRAYOID: return oatpp::Vector<Float32>::Class::getType ();
283
+
282
284
case UUIDOID: return oatpp::postgresql::Uuid::Class::getType ();
283
285
284
286
}
@@ -314,21 +316,78 @@ oatpp::Void Deserializer::deserializeUuid(const Deserializer* _this, const InDat
314
316
315
317
}
316
318
319
+ // after https://stackoverflow.com/questions/4016412/postgresqls-libpq-encoding-for-binary-transport-of-array-data
320
+ struct PgArray {
321
+ int32_t ndim; // Number of dimensions
322
+ int32_t _ign; // offset for data, removed by libpq
323
+ Oid oid; // type of element in the array
324
+
325
+ // Start of array (1st dimension)
326
+ int32_t size; // Number of elements
327
+ int32_t index; // Index of first element
328
+ int32_t elem; // Beginning of (size, value) elements
329
+ };
330
+
317
331
oatpp::Void Deserializer::deserializeArray (const Deserializer* _this, const InData& data, const Type* type) {
318
332
319
333
(void ) _this;
320
334
(void ) type;
321
335
322
- switch (data.oid ) {
323
- case FLOAT4ARRAYOID: return oatpp::Vector<Float32>();
324
- case FLOAT8ARRAYOID: return oatpp::Vector<Float64>();
336
+ // Place to put our data
337
+ oatpp::Void retval = nullptr ;
338
+
339
+ // see if we handle this type
340
+ switch (data.oid ) {
341
+ case FLOAT8ARRAYOID:
342
+ break ;
343
+ default :
344
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Deserializer::deserializeArray()]: Unhandled array type." );
325
345
}
326
346
327
- if (data.isNull ) {
328
- return oatpp::postgresql::Uuid ();
347
+ // parse out the array
348
+ if (!data.isNull ) {
349
+ auto *pgArray = reinterpret_cast <const PgArray *>(data.data );
350
+
351
+ // everything is in network order!!!
352
+ // only handle 1d array for now
353
+ if (ntohl (pgArray->ndim ) > 1 ) {
354
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Deserializer::deserializeArray()]: Dimension > 1" );
355
+ }
356
+
357
+ // make sure data is the right type
358
+ if (ntohl (pgArray->oid ) == FLOAT8OID) {
359
+ // build the array
360
+ auto vec = oatpp::Vector<Float64>::createShared ();
361
+ auto pElem = &pgArray->elem ;
362
+ auto nElem = ntohl (*pElem);
363
+ for (int i = 0 ; i < nElem; i++) {
364
+ // get element size, point to element data
365
+ auto elemSize = ntohl (*pElem++);
366
+ // quit if we get an empty element
367
+ if (elemSize == 0 ) {
368
+ break ;
369
+ }
370
+ // make sure element size matches the data size
371
+ if (elemSize != sizeof (v_float64)) {
372
+ throw std::runtime_error (
373
+ " [oatpp::postgresql::mapping::Deserializer::deserializeArray()]: Bad element size" );
374
+ }
375
+ // get the 64 bit host order data, pointing to next element
376
+ // TODO: make sure this matches element size
377
+ v_int64 l1 = ntohl (*pElem++);
378
+ v_int64 l2 = ntohl (*pElem++);
379
+ v_int64 intVal = (l1 << 32 ) | l2 ;
380
+ v_float64 val = *reinterpret_cast <p_float64>(&intVal);
381
+ vec->push_back (val);
382
+ }
383
+ retval = vec;
384
+ } else {
385
+ throw std::runtime_error (
386
+ " [oatpp::postgresql::mapping::Deserializer::deserializeArray()]: Unhandled array value type." );
387
+ }
329
388
}
330
389
331
- return postgresql::Uuid ((p_char8)data. data ) ;
390
+ return retval ;
332
391
}
333
392
334
393
}}}
0 commit comments