Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit de45c16

Browse files
Merge pull request #6 from oatpp/arrays
Arrays
2 parents 723bf2d + b109c46 commit de45c16

File tree

13 files changed

+1256
-29
lines changed

13 files changed

+1256
-29
lines changed

‎README.md‎

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,16 @@ public:
6060
6161
### Supported Data Types
6262
63-
- INT2
64-
- INT4
65-
- INT8
66-
- TIMESTAMP
67-
- TEXT
68-
- VARCHAR
69-
- FLOAT4
70-
- FLOAT8
71-
- BOOL
72-
- UUID
63+
|Type|Supported|In Array|
64+
|---|:---:|:---:|
65+
|INT2|+|+|
66+
|INT4|+|+|
67+
|INT8|+|+|
68+
|TIMESTAMP|+|+|
69+
|TEXT|+|+|
70+
|VARCHAR|+|+|
71+
|FLOAT4|+|+|
72+
|FLOAT8|+|+|
73+
|BOOL|+|+|
74+
|UUID|+|+|
75+
|**Other Types**|-|-|

‎src/CMakeLists.txt‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ add_library(${OATPP_THIS_MODULE_NAME}
55
oatpp-postgresql/mapping/Deserializer.cpp
66
oatpp-postgresql/mapping/Deserializer.hpp
77
oatpp-postgresql/mapping/Oid.hpp
8+
oatpp-postgresql/mapping/PgArray.cpp
9+
oatpp-postgresql/mapping/PgArray.hpp
810
oatpp-postgresql/mapping/ResultMapper.cpp
911
oatpp-postgresql/mapping/ResultMapper.hpp
1012
oatpp-postgresql/mapping/Serializer.cpp

‎src/oatpp-postgresql/mapping/Deserializer.cpp‎

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,9 @@
2525
#include "Deserializer.hpp"
2626

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

30-
#if defined(WIN32) || defined(_WIN32)
31-
#include <WinSock2.h>
32-
#else
33-
#include <arpa/inet.h>
34-
#endif
35-
3631
namespace oatpp { namespace postgresql { namespace mapping {
3732

3833
Deserializer::InData::InData(PGresult* dbres, int row, int col, const std::shared_ptr<const data::mapping::TypeResolver>& pTypeResolver) {
@@ -69,9 +64,9 @@ Deserializer::Deserializer() {
6964
setDeserializerMethod(data::mapping::type::__class::AbstractObject::CLASS_ID, nullptr);
7065
setDeserializerMethod(data::mapping::type::__class::AbstractEnum::CLASS_ID, &Deserializer::deserializeEnum);
7166

72-
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, nullptr);
73-
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, nullptr);
74-
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, nullptr);
67+
setDeserializerMethod(data::mapping::type::__class::AbstractVector::CLASS_ID, &Deserializer::deserializeArray<oatpp::AbstractVector>);
68+
setDeserializerMethod(data::mapping::type::__class::AbstractList::CLASS_ID, &Deserializer::deserializeArray<oatpp::AbstractList>);
69+
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID, &Deserializer::deserializeArray<oatpp::AbstractUnorderedSet>);
7570

7671
setDeserializerMethod(data::mapping::type::__class::AbstractPairList::CLASS_ID, nullptr);
7772
setDeserializerMethod(data::mapping::type::__class::AbstractUnorderedMap::CLASS_ID, nullptr);
@@ -261,9 +256,9 @@ oatpp::Void Deserializer::deserializeEnum(const Deserializer* _this, const InDat
261256

262257
}
263258

264-
const oatpp::Type* Deserializer::guessAnyType(Oid oid) {
259+
const oatpp::Type* Deserializer::guessAnyType(const InData& data) {
265260

266-
switch(oid) {
261+
switch(data.oid) {
267262

268263
case TEXTOID:
269264
case VARCHAROID: return oatpp::String::Class::getType();
@@ -281,6 +276,24 @@ const oatpp::Type* Deserializer::guessAnyType(Oid oid) {
281276

282277
case UUIDOID: return oatpp::postgresql::Uuid::Class::getType();
283278

279+
// Arrays
280+
281+
case TEXTARRAYOID:
282+
case VARCHARARRAYOID: return generateMultidimensionalArrayType<oatpp::String>(data);
283+
284+
case INT2ARRAYOID: return generateMultidimensionalArrayType<oatpp::Int16>(data);
285+
case INT4ARRAYOID: return generateMultidimensionalArrayType<oatpp::Int32>(data);
286+
case INT8ARRAYOID: return generateMultidimensionalArrayType<oatpp::Int64>(data);
287+
288+
case FLOAT4ARRAYOID: return generateMultidimensionalArrayType<oatpp::Float32>(data);
289+
case FLOAT8ARRAYOID: return generateMultidimensionalArrayType<oatpp::Float64>(data);
290+
291+
case BOOLARRAYOID: return generateMultidimensionalArrayType<oatpp::Boolean>(data);
292+
293+
case TIMESTAMPARRAYOID: return generateMultidimensionalArrayType<oatpp::UInt64>(data);
294+
295+
case UUIDARRAYOID: return generateMultidimensionalArrayType<oatpp::postgresql::Uuid>(data);
296+
284297
}
285298

286299
return nullptr;
@@ -290,7 +303,11 @@ oatpp::Void Deserializer::deserializeAny(const Deserializer* _this, const InData
290303

291304
(void) type;
292305

293-
const Type* valueType = guessAnyType(data.oid);
306+
if(data.isNull) {
307+
return oatpp::Any();
308+
}
309+
310+
const Type* valueType = guessAnyType(data);
294311
if(valueType == nullptr) {
295312
throw std::runtime_error("[oatpp::postgresql::mapping::Deserializer::deserializeAny()]: Error. Unknown OID.");
296313
}
@@ -314,4 +331,25 @@ oatpp::Void Deserializer::deserializeUuid(const Deserializer* _this, const InDat
314331

315332
}
316333

334+
oatpp::Void Deserializer::deserializeSubArray(const Type* type,
335+
ArrayDeserializationMeta& meta,
336+
v_int32 dimension)
337+
{
338+
339+
if(data::mapping::type::__class::AbstractVector::CLASS_ID.id == type->classId.id) {
340+
return deserializeSubArray<oatpp::AbstractVector>(type, meta, dimension);
341+
342+
} else if(data::mapping::type::__class::AbstractList::CLASS_ID.id == type->classId.id) {
343+
return deserializeSubArray<oatpp::AbstractList>(type, meta, dimension);
344+
345+
} else if(data::mapping::type::__class::AbstractUnorderedSet::CLASS_ID.id == type->classId.id) {
346+
return deserializeSubArray<oatpp::AbstractUnorderedSet>(type, meta, dimension);
347+
348+
}
349+
350+
throw std::runtime_error("[oatpp::postgresql::mapping::Deserializer::deserializeSubArray()]: "
351+
"Error. Unknown 1D collection type.");
352+
353+
}
354+
317355
}}}

‎src/oatpp-postgresql/mapping/Deserializer.hpp‎

Lines changed: 145 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,20 @@
2525
#ifndef oatpp_postgresql_mapping_Deserializer_hpp
2626
#define oatpp_postgresql_mapping_Deserializer_hpp
2727

28+
#include "PgArray.hpp"
29+
30+
#include "oatpp/core/data/stream/BufferStream.hpp"
2831
#include "oatpp/core/data/mapping/TypeResolver.hpp"
2932
#include "oatpp/core/Types.hpp"
3033

3134
#include <libpq-fe.h>
3235

36+
#if defined(WIN32) || defined(_WIN32)
37+
#include <WinSock2.h>
38+
#else
39+
#include <arpa/inet.h>
40+
#endif
41+
3342
namespace oatpp { namespace postgresql { namespace mapping {
3443

3544
/**
@@ -40,6 +49,8 @@ class Deserializer {
4049

4150
struct InData {
4251

52+
InData() = default;
53+
4354
InData(PGresult* dbres, int row, int col, const std::shared_ptr<const data::mapping::TypeResolver>& pTypeResolver);
4455

4556
std::shared_ptr<const data::mapping::TypeResolver> typeResolver;
@@ -59,7 +70,7 @@ class Deserializer {
5970
static v_int64 deInt8(const InData& data);
6071
static v_int64 deInt(const InData& data);
6172

62-
static const oatpp::Type* guessAnyType(Oid oid);
73+
static const oatpp::Type* guessAnyType(const InData& data);
6374
private:
6475
std::vector<DeserializerMethod> m_methods;
6576
public:
@@ -96,6 +107,139 @@ class Deserializer {
96107

97108
static oatpp::Void deserializeUuid(const Deserializer* _this, const InData& data, const Type* type);
98109

110+
template<typename T>
111+
static const oatpp::Type* generateMultidimensionalArrayType(const InData& data) {
112+
113+
if(data.size < sizeof(v_int32)) {
114+
return nullptr;
115+
}
116+
117+
auto ndim = (v_int32) ntohl(*((p_int32)data.data));
118+
119+
switch (ndim) {
120+
121+
case 0: return MultidimensionalArray<T, 1>::getClassType();
122+
case 1: return MultidimensionalArray<T, 1>::getClassType();
123+
case 2: return MultidimensionalArray<T, 2>::getClassType();
124+
case 3: return MultidimensionalArray<T, 3>::getClassType();
125+
case 4: return MultidimensionalArray<T, 4>::getClassType();
126+
case 5: return MultidimensionalArray<T, 5>::getClassType();
127+
case 6: return MultidimensionalArray<T, 6>::getClassType();
128+
case 7: return MultidimensionalArray<T, 7>::getClassType();
129+
case 8: return MultidimensionalArray<T, 8>::getClassType();
130+
case 9: return MultidimensionalArray<T, 9>::getClassType();
131+
case 10: return MultidimensionalArray<T, 10>::getClassType(); // Max 10 dimensions should be enough :)
132+
133+
default:
134+
break;
135+
136+
}
137+
138+
return nullptr;
139+
140+
}
141+
142+
struct ArrayDeserializationMeta {
143+
144+
ArrayDeserializationMeta(const Deserializer* p_this,
145+
const InData* pData)
146+
: _this(p_this)
147+
, data(pData)
148+
, stream(nullptr, (p_char8)pData->data, pData->size)
149+
{
150+
ArrayUtils::readArrayHeader(&stream, arrayHeader, dimensions);
151+
}
152+
153+
const Deserializer* _this;
154+
const InData* data;
155+
data::stream::BufferInputStream stream;
156+
PgArrayHeader arrayHeader;
157+
std::vector<v_int32> dimensions;
158+
159+
};
160+
161+
static oatpp::Void deserializeSubArray(const Type* type,
162+
ArrayDeserializationMeta& meta,
163+
v_int32 dimension);
164+
165+
template<class Collection>
166+
static oatpp::Void deserializeSubArray(const Type* type,
167+
ArrayDeserializationMeta& meta,
168+
v_int32 dimension)
169+
{
170+
171+
if(dimension < meta.dimensions.size() - 1) {
172+
173+
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
174+
auto itemType = *type->params.begin();
175+
auto listWrapper = polymorphicDispatcher->createObject();
176+
177+
auto size = meta.dimensions[dimension];
178+
179+
for(v_int32 i = 0; i < size; i ++) {
180+
const auto& item = deserializeSubArray(itemType, meta, dimension + 1);
181+
polymorphicDispatcher->addPolymorphicItem(listWrapper, item);
182+
}
183+
184+
return oatpp::Void(listWrapper.getPtr(), listWrapper.valueType);
185+
186+
} else if(dimension == meta.dimensions.size() - 1) {
187+
188+
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
189+
auto itemType = *type->params.begin();
190+
auto listWrapper = polymorphicDispatcher->createObject();
191+
192+
auto size = meta.dimensions[dimension];
193+
194+
for(v_int32 i = 0; i < size; i ++) {
195+
196+
v_int32 dataSize;
197+
meta.stream.readSimple(&dataSize, sizeof(v_int32));
198+
199+
InData itemData;
200+
itemData.typeResolver = meta.data->typeResolver;
201+
itemData.size = (v_int32) ntohl(dataSize);
202+
itemData.data = (const char*) &meta.stream.getData()[meta.stream.getCurrentPosition()];
203+
itemData.oid = meta.arrayHeader.oid;
204+
itemData.isNull = itemData.size < 0;
205+
206+
if(itemData.size > 0) {
207+
meta.stream.setCurrentPosition(meta.stream.getCurrentPosition() + itemData.size);
208+
}
209+
210+
const auto& item = meta._this->deserialize(itemData, itemType);
211+
212+
polymorphicDispatcher->addPolymorphicItem(listWrapper, item);
213+
214+
}
215+
216+
return oatpp::Void(listWrapper.getPtr(), listWrapper.valueType);
217+
218+
}
219+
220+
throw std::runtime_error("[oatpp::postgresql::mapping::Deserializer::deserializeSubArray()]: "
221+
"Error. Invalid state: dimension >= dimensions.size().");
222+
223+
}
224+
225+
template<class Collection>
226+
static oatpp::Void deserializeArray(const Deserializer* _this, const InData& data, const Type* type) {
227+
228+
if(data.isNull) {
229+
return oatpp::Void(nullptr, type);
230+
}
231+
232+
auto ndim = (v_int32) ntohl(*((p_int32)data.data));
233+
if(ndim == 0) {
234+
auto polymorphicDispatcher = static_cast<const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher);
235+
return polymorphicDispatcher->createObject(); // empty array
236+
}
237+
238+
ArrayDeserializationMeta meta(_this, &data);
239+
return deserializeSubArray(type, meta, 0);
240+
241+
}
242+
99243
};
100244

101245
}}}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /