25
25
#ifndef oatpp_postgresql_mapping_Deserializer_hpp
26
26
#define oatpp_postgresql_mapping_Deserializer_hpp
27
27
28
+ #include " PgArray.hpp"
29
+
30
+ #include " oatpp/core/data/stream/BufferStream.hpp"
28
31
#include " oatpp/core/data/mapping/TypeResolver.hpp"
29
32
#include " oatpp/core/Types.hpp"
30
33
31
34
#include < libpq-fe.h>
32
35
36
+ #if defined(WIN32) || defined(_WIN32)
37
+ #include < WinSock2.h>
38
+ #else
39
+ #include < arpa/inet.h>
40
+ #endif
41
+
33
42
namespace oatpp { namespace postgresql { namespace mapping {
34
43
35
44
/* *
@@ -40,6 +49,8 @@ class Deserializer {
40
49
41
50
struct InData {
42
51
52
+ InData () = default ;
53
+
43
54
InData (PGresult* dbres, int row, int col, const std::shared_ptr<const data::mapping::TypeResolver>& pTypeResolver);
44
55
45
56
std::shared_ptr<const data::mapping::TypeResolver> typeResolver;
@@ -59,7 +70,7 @@ class Deserializer {
59
70
static v_int64 deInt8 (const InData& data);
60
71
static v_int64 deInt (const InData& data);
61
72
62
- static const oatpp::Type* guessAnyType (Oid oid );
73
+ static const oatpp::Type* guessAnyType (const InData& data );
63
74
private:
64
75
std::vector<DeserializerMethod> m_methods;
65
76
public:
@@ -96,6 +107,139 @@ class Deserializer {
96
107
97
108
static oatpp::Void deserializeUuid (const Deserializer* _this, const InData& data, const Type* type);
98
109
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
+
99
243
};
100
244
101
245
}}}
0 commit comments