@@ -65,40 +65,65 @@ void Serializer::setSerializerMethods() {
65
65
66
66
setSerializerMethod (data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::serializeEnum);
67
67
68
+ setSerializerMethod (data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeArray2<oatpp::AbstractVector>);
69
+ setSerializerMethod (data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::serializeArray2<oatpp::AbstractList>);
70
+ setSerializerMethod (data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::serializeArray2<oatpp::AbstractUnorderedSet>);
71
+
68
72
// //
69
73
70
74
setSerializerMethod (postgresql::mapping::type::__class::Uuid::CLASS_ID, &Serializer::serializeUuid);
71
- setSerializerMethod (data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::serializeArray);
72
75
73
76
}
74
77
75
78
void Serializer::setTypeOidMethods () {
76
79
77
80
m_typeOidMethods.resize (data::mapping::type::ClassId::getClassCount (), nullptr );
81
+ m_arrayTypeOidMethods.resize (data::mapping::type::ClassId::getClassCount (), nullptr );
78
82
79
83
setTypeOidMethod (data::mapping::type::__class::String::CLASS_ID, &Serializer::getTypeOid<TEXTOID>);
84
+ setArrayTypeOidMethod (data::mapping::type::__class::String::CLASS_ID, &Serializer::getTypeOid<TEXTARRAYOID>);
80
85
81
86
setTypeOidMethod (data::mapping::type::__class::Int8::CLASS_ID, &Serializer::getTypeOid<INT2OID>);
87
+ setArrayTypeOidMethod (data::mapping::type::__class::Int8::CLASS_ID, &Serializer::getTypeOid<INT2ARRAYOID>);
88
+
82
89
setTypeOidMethod (data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::getTypeOid<INT2OID>);
90
+ setArrayTypeOidMethod (data::mapping::type::__class::UInt8::CLASS_ID, &Serializer::getTypeOid<INT2ARRAYOID>);
83
91
84
92
setTypeOidMethod (data::mapping::type::__class::Int16::CLASS_ID, &Serializer::getTypeOid<INT2OID>);
93
+ setArrayTypeOidMethod (data::mapping::type::__class::Int16::CLASS_ID, &Serializer::getTypeOid<INT2ARRAYOID>);
94
+
85
95
setTypeOidMethod (data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::getTypeOid<INT4OID>);
96
+ setArrayTypeOidMethod (data::mapping::type::__class::UInt16::CLASS_ID, &Serializer::getTypeOid<INT4ARRAYOID>);
86
97
87
98
setTypeOidMethod (data::mapping::type::__class::Int32::CLASS_ID, &Serializer::getTypeOid<INT4OID>);
99
+ setArrayTypeOidMethod (data::mapping::type::__class::Int32::CLASS_ID, &Serializer::getTypeOid<INT4ARRAYOID>);
100
+
88
101
setTypeOidMethod (data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::getTypeOid<INT8OID>);
102
+ setArrayTypeOidMethod (data::mapping::type::__class::UInt32::CLASS_ID, &Serializer::getTypeOid<INT8ARRAYOID>);
89
103
90
104
setTypeOidMethod (data::mapping::type::__class::Int64::CLASS_ID, &Serializer::getTypeOid<INT8OID>);
105
+ setArrayTypeOidMethod (data::mapping::type::__class::Int64::CLASS_ID, &Serializer::getTypeOid<INT8ARRAYOID>);
91
106
92
107
setTypeOidMethod (data::mapping::type::__class::Float32::CLASS_ID, &Serializer::getTypeOid<FLOAT4OID>);
108
+ setArrayTypeOidMethod (data::mapping::type::__class::Float32::CLASS_ID, &Serializer::getTypeOid<FLOAT4ARRAYOID>);
109
+
93
110
setTypeOidMethod (data::mapping::type::__class::Float64::CLASS_ID, &Serializer::getTypeOid<FLOAT8OID>);
111
+ setArrayTypeOidMethod (data::mapping::type::__class::Float64::CLASS_ID, &Serializer::getTypeOid<FLOAT8ARRAYOID>);
112
+
94
113
setTypeOidMethod (data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::getTypeOid<BOOLOID>);
114
+ setArrayTypeOidMethod (data::mapping::type::__class::Boolean::CLASS_ID, &Serializer::getTypeOid<BOOLARRAYOID>);
115
+
116
+ setTypeOidMethod (data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::get1DCollectionOid);
117
+ setTypeOidMethod (data::mapping::type::__class::AbstractList::CLASS_ID, &Serializer::get1DCollectionOid);
118
+ setTypeOidMethod (data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Serializer::get1DCollectionOid);
95
119
96
- setTypeOidMethod (data::mapping::type::__class::AbstractVector::CLASS_ID, &Serializer::getTypeOid<FLOAT8ARRAYOID>);
120
+ setTypeOidMethod (data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::getEnumTypeOid);
121
+ setArrayTypeOidMethod (data::mapping::type::__class::AbstractEnum::CLASS_ID, &Serializer::getEnumArrayTypeOid);
97
122
98
123
// //
99
124
100
125
setTypeOidMethod (postgresql::mapping::type::__class::Uuid::CLASS_ID, &Serializer::getTypeOid<UUIDOID>);
101
- setTypeOidMethod (data ::mapping::type::__class::AbstractEnum ::CLASS_ID, &Serializer::getEnumTypeOid );
126
+ setArrayTypeOidMethod (postgresql ::mapping::type::__class::Uuid ::CLASS_ID, &Serializer::getTypeOid<UUIDARRAYOID> );
102
127
103
128
}
104
129
@@ -113,13 +138,22 @@ void Serializer::setSerializerMethod(const data::mapping::type::ClassId& classId
113
138
114
139
void Serializer::setTypeOidMethod (const data::mapping::type::ClassId& classId, TypeOidMethod method) {
115
140
const v_uint32 id = classId.id ;
116
- if (id < m_methods .size ()) {
141
+ if (id < m_typeOidMethods .size ()) {
117
142
m_typeOidMethods[id] = method;
118
143
} else {
119
144
throw std::runtime_error (" [oatpp::postgresql::mapping::Serializer::setTypeOidMethod()]: Error. Unknown classId" );
120
145
}
121
146
}
122
147
148
+ void Serializer::setArrayTypeOidMethod (const data::mapping::type::ClassId& classId, TypeOidMethod method) {
149
+ const v_uint32 id = classId.id ;
150
+ if (id < m_arrayTypeOidMethods.size ()) {
151
+ m_arrayTypeOidMethods[id] = method;
152
+ } else {
153
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Serializer::setArrayTypeOidMethod()]: Error. Unknown classId" );
154
+ }
155
+ }
156
+
123
157
void Serializer::serialize (OutputData& outData, const oatpp::Void& polymorph) const {
124
158
auto id = polymorph.valueType ->classId .id ;
125
159
auto & method = m_methods[id];
@@ -146,13 +180,27 @@ Oid Serializer::getTypeOid(const oatpp::Type* type) const {
146
180
147
181
}
148
182
183
+ Oid Serializer::getArrayTypeOid (const oatpp::Type* type) const {
184
+
185
+ auto id = type->classId .id ;
186
+ auto & method = m_arrayTypeOidMethods[id];
187
+ if (method) {
188
+ return (*method)(this , type);
189
+ }
190
+
191
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Serializer::getArrayTypeOid()]: "
192
+ " Error. Can't derive OID for type '" + std::string (type->classId .name ) +
193
+ " '" );
194
+
195
+ }
196
+
149
197
// //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
150
198
// Serializer utility functions
151
199
152
200
void Serializer::serNull (OutputData& outData) {
153
201
outData.dataBuffer .reset ();
154
202
outData.data = nullptr ;
155
- outData.dataSize = 0 ;
203
+ outData.dataSize = - 1 ;
156
204
outData.dataFormat = 1 ;
157
205
}
158
206
@@ -377,6 +425,30 @@ Oid Serializer::getEnumTypeOid(const Serializer* _this, const oatpp::Type* type)
377
425
378
426
}
379
427
428
+ Oid Serializer::getEnumArrayTypeOid (const Serializer* _this, const oatpp::Type* type) {
429
+
430
+ auto polymorphicDispatcher = static_cast <const data::mapping::type::__class::AbstractEnum::PolymorphicDispatcher*>(
431
+ type->polymorphicDispatcher
432
+ );
433
+
434
+ const oatpp::Type* enumInterType = polymorphicDispatcher->getInterpretationType ();
435
+ return _this->getArrayTypeOid (enumInterType);
436
+
437
+ }
438
+
439
+ Oid Serializer::get1DCollectionOid (const Serializer* _this, const oatpp::Type* type) {
440
+
441
+ while (type->classId .id == oatpp::AbstractVector::Class::CLASS_ID.id ||
442
+ type->classId .id == oatpp::AbstractList::Class::CLASS_ID.id ||
443
+ type->classId .id == oatpp::AbstractUnorderedSet::Class::CLASS_ID.id )
444
+ {
445
+ type = *type->params .begin ();
446
+ }
447
+
448
+ return _this->getArrayTypeOid (type);
449
+
450
+ }
451
+
380
452
void Serializer::serializeUuid (const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph) {
381
453
382
454
(void ) _this;
@@ -392,46 +464,106 @@ void Serializer::serializeUuid(const Serializer* _this, OutputData& outData, con
392
464
}
393
465
}
394
466
395
- void Serializer::serializeArray (const Serializer* _this, OutputData& outData, const oatpp::Void& polymorph) {
396
-
397
- (void ) _this;
398
-
399
- if (polymorph) {
400
- auto v = polymorph.staticCast <oatpp::Vector<Float64>>();
401
-
402
- // get size of header + vector size * sizeof each element (size + data)
403
- auto dataSize = sizeof (PgArrayHeader) + v->size () * (sizeof (PgElem) + sizeof (v_float64));
404
- outData.dataBuffer .reset (new char [dataSize]);
405
- outData.dataSize = dataSize;
406
- outData.dataFormat = 1 ;
407
- 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 = htonl (1 ); // postgres arrays are indexed 1..N by default
419
-
420
- // stuff in the elements in network order
421
- auto *elemBuff = reinterpret_cast <p_uint8>(pgArray->elem );
422
- for (int i=0 ; i < v->size (); i++) {
423
- *reinterpret_cast <p_uint32>(elemBuff) = htonl (sizeof (v_float64));
424
- elemBuff += sizeof (v_int32);
425
- v_float64 fValue = v->at (i);
426
- auto pVal = reinterpret_cast <p_int64>(&fValue );
427
- *reinterpret_cast <p_uint32>(elemBuff) = htonl (*pVal >> 32 );
428
- elemBuff += sizeof (v_int32);
429
- *reinterpret_cast <p_uint32>(elemBuff) = htonl (*pVal & 0xFFFFFFFF );
430
- elemBuff += sizeof (v_int32);
431
- }
432
- } else {
433
- serNull (outData);
467
+ const oatpp::Type* Serializer::getArrayItemTypeAndDimensions (const oatpp::Void& polymorph, std::vector<v_int32>& dimensions) {
468
+
469
+ void * currObj = polymorph.get ();
470
+ const oatpp::Type* currType = polymorph.valueType ;
471
+
472
+ while (currType->classId .id == oatpp::AbstractVector::Class::CLASS_ID.id ||
473
+ currType->classId .id == oatpp::AbstractList::Class::CLASS_ID.id ||
474
+ currType->classId .id == oatpp::AbstractUnorderedSet::Class::CLASS_ID.id )
475
+ {
476
+
477
+ if (currObj == nullptr ) {
478
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Serializer::getArrayItemTypeAndDimensions()]: Error. "
479
+ " The nested container can't be null." );
480
+ }
481
+
482
+ if (currType->classId .id == oatpp::AbstractVector::Class::CLASS_ID.id ) {
483
+
484
+ auto c = static_cast <std::vector<oatpp::Void>*>(currObj);
485
+ dimensions.push_back (c->size ());
486
+ currObj = (c->size () > 0 ) ? (*c)[0 ].get () : nullptr ;
487
+
488
+ } else if (currType->classId .id == oatpp::AbstractList::Class::CLASS_ID.id ) {
489
+
490
+ auto c = static_cast <std::list<oatpp::Void>*>(currObj);
491
+ dimensions.push_back (c->size ());
492
+ currObj = (c->size () > 0 ) ? c->front ().get () : nullptr ;
493
+
494
+
495
+ } else if (currType->classId .id == oatpp::AbstractUnorderedSet::Class::CLASS_ID.id ) {
496
+
497
+ auto c = static_cast <std::unordered_set<oatpp::Void>*>(currObj);
498
+ dimensions.push_back (c->size ());
499
+ currObj = (c->size () > 0 ) ? c->begin ()->get () : nullptr ;
500
+
434
501
}
502
+
503
+ currType = *currType->params .begin ();
504
+
505
+ }
506
+
507
+ return currType;
508
+
509
+ }
510
+
511
+ void Serializer::writeArrayHeader (data::stream::ConsistentOutputStream* stream,
512
+ Oid itemOid,
513
+ const std::vector<v_int32>& dimensions)
514
+ {
515
+
516
+ // num dimensions
517
+ v_int32 v = htonl (dimensions.size ());
518
+ stream->writeSimple (&v, sizeof (v_int32));
519
+
520
+ // ignore
521
+ v = 0 ;
522
+ stream->writeSimple (&v, sizeof (v_int32));
523
+
524
+ // oid
525
+ v = htonl (itemOid);
526
+ stream->writeSimple (&v, sizeof (v_int32));
527
+
528
+ // size
529
+ v = htonl (dimensions[0 ]);
530
+ stream->writeSimple (&v, sizeof (v_int32));
531
+
532
+ // index
533
+ v = htonl (1 );
534
+ stream->writeSimple (&v, sizeof (v_int32));
535
+
536
+ for (v_uint32 i = 1 ; i < dimensions.size (); i++) {
537
+ v_int32 size = htonl (dimensions[i]);
538
+ v_int32 index = htonl (1 );
539
+ stream->writeSimple (&size, sizeof (v_int32));
540
+ stream->writeSimple (&index, sizeof (v_int32));
541
+ }
542
+
543
+ }
544
+
545
+ void Serializer::serializeSubArray (data::stream::ConsistentOutputStream* stream,
546
+ const oatpp::Void& polymorph,
547
+ ArraySerializationMeta& meta,
548
+ v_int32 dimension)
549
+ {
550
+
551
+ const oatpp::Type* type = polymorph.valueType ;
552
+
553
+ if (data::mapping::type::__class::AbstractVector::CLASS_ID.id == type->classId .id ) {
554
+ return serializeSubArray<oatpp::AbstractVector>(stream, polymorph, meta, dimension);
555
+
556
+ } else if (data::mapping::type::__class::AbstractList::CLASS_ID.id == type->classId .id ) {
557
+ return serializeSubArray<oatpp::AbstractList>(stream, polymorph, meta, dimension);
558
+
559
+ } else if (data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id == type->classId .id ) {
560
+ return serializeSubArray<oatpp::AbstractUnorderedSet>(stream, polymorph, meta, dimension);
561
+
562
+ }
563
+
564
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Serializer::serializeSubArray()]: "
565
+ " Error. Unknown 1D collection type." );
566
+
435
567
}
436
568
437
569
}}}
0 commit comments