@@ -69,7 +69,7 @@ class Deserializer {
69
69
static v_int64 deInt8 (const InData& data);
70
70
static v_int64 deInt (const InData& data);
71
71
72
- static const oatpp::Type* guessAnyType (Oid oid );
72
+ static const oatpp::Type* guessAnyType (const InData& data );
73
73
private:
74
74
std::vector<DeserializerMethod> m_methods;
75
75
public:
@@ -106,44 +106,151 @@ class Deserializer {
106
106
107
107
static oatpp::Void deserializeUuid (const Deserializer* _this, const InData& data, const Type* type);
108
108
109
+ template <typename T>
110
+ static const oatpp::Type* generateMultidimensionalArrayType (const InData& data) {
111
+
112
+ if (data.size < sizeof (v_int32)) {
113
+ return nullptr ;
114
+ }
115
+
116
+ auto ndim = (v_int32) htonl (*((p_int32)data.data ));
117
+
118
+ switch (ndim) {
119
+
120
+ case 0 : return MultidimensionalArray<T, 1 >::getClassType ();
121
+ case 1 : return MultidimensionalArray<T, 1 >::getClassType ();
122
+ case 2 : return MultidimensionalArray<T, 2 >::getClassType ();
123
+ case 3 : return MultidimensionalArray<T, 3 >::getClassType ();
124
+ case 4 : return MultidimensionalArray<T, 4 >::getClassType ();
125
+ case 5 : return MultidimensionalArray<T, 5 >::getClassType ();
126
+ case 6 : return MultidimensionalArray<T, 6 >::getClassType ();
127
+ case 7 : return MultidimensionalArray<T, 7 >::getClassType ();
128
+ case 8 : return MultidimensionalArray<T, 8 >::getClassType ();
129
+ case 9 : return MultidimensionalArray<T, 9 >::getClassType ();
130
+ case 10 : return MultidimensionalArray<T, 10 >::getClassType (); // Max 10 dimensions should be enough :)
131
+
132
+ default :
133
+ break ;
134
+
135
+ }
136
+
137
+ return nullptr ;
138
+
139
+ }
140
+
141
+ struct ArrayDeserializationMeta {
142
+
143
+ const Deserializer* _this;
144
+ const InData* data;
145
+ PgArrayHeader arrayHeader;
146
+ p_char8 payload;
147
+ std::vector<v_int32> dimensions;
148
+
149
+ };
150
+
151
+ static oatpp::Void deserializeSubArray (const Type* type,
152
+ ArrayDeserializationMeta& meta,
153
+ v_int32 dimension);
154
+
155
+ template <class Collection >
156
+ static oatpp::Void deserializeSubArray (const Type* type,
157
+ ArrayDeserializationMeta& meta,
158
+ v_int32 dimension)
159
+ {
160
+
161
+ if (dimension < meta.dimensions .size () - 1 ) {
162
+
163
+ auto polymorphicDispatcher = static_cast <const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher );
164
+ auto itemType = *type->params .begin ();
165
+ auto listWrapper = polymorphicDispatcher->createObject ();
166
+
167
+ auto size = meta.dimensions [dimension];
168
+
169
+ for (v_int32 i = 0 ; i < size; i ++) {
170
+ const auto & item = deserializeSubArray (itemType, meta, dimension + 1 );
171
+ polymorphicDispatcher->addPolymorphicItem (listWrapper, item);
172
+ }
173
+
174
+ return oatpp::Void (listWrapper.getPtr (), listWrapper.valueType );
175
+
176
+ } else if (dimension == meta.dimensions .size () - 1 ) {
177
+
178
+ auto polymorphicDispatcher = static_cast <const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher );
179
+ auto itemType = *type->params .begin ();
180
+ auto listWrapper = polymorphicDispatcher->createObject ();
181
+
182
+ auto size = meta.dimensions [dimension];
183
+
184
+ for (v_int32 i = 0 ; i < size; i ++) {
185
+
186
+ InData itemData;
187
+ itemData.typeResolver = meta.data ->typeResolver ;
188
+ itemData.size = (v_int32)ntohl (*((p_int32) meta.payload ));
189
+ itemData.data = (const char *) (meta.payload + sizeof (v_int32));
190
+ itemData.oid = meta.arrayHeader .oid ;
191
+ itemData.isNull = itemData.size < 0 ;
192
+
193
+ if (itemData.size > 0 ) {
194
+ meta.payload += sizeof (v_int32) + itemData.size ;
195
+ } else {
196
+ meta.payload += sizeof (v_int32);
197
+ }
198
+
199
+ const auto & item = meta._this ->deserialize (itemData, itemType);
200
+
201
+ polymorphicDispatcher->addPolymorphicItem (listWrapper, item);
202
+
203
+ }
204
+
205
+ return oatpp::Void (listWrapper.getPtr (), listWrapper.valueType );
206
+
207
+ }
208
+
209
+ throw std::runtime_error (" [oatpp::postgresql::mapping::Deserializer::deserializeSubArray()]: "
210
+ " Error. Invalid state: dimension >= dimensions.size()." );
211
+
212
+ }
213
+
109
214
template <class Collection >
110
215
static oatpp::Void deserializeArray2 (const Deserializer* _this, const InData& data, const Type* type) {
111
216
112
217
if (data.isNull ) {
113
218
return oatpp::Void (nullptr , type);
114
219
}
115
220
116
- auto polymorphicDispatcher = static_cast <const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher );
117
- auto itemType = *type->params .begin (); // Get "wanted" type of the list item
118
- auto listWrapper = polymorphicDispatcher->createObject (); // Instantiate list of the "wanted" type
221
+ auto ndim = (v_int32) htonl (*((p_int32)data.data ));
222
+ if (ndim == 0 ) {
223
+ auto polymorphicDispatcher = static_cast <const typename Collection::Class::PolymorphicDispatcher*>(type->polymorphicDispatcher );
224
+ return polymorphicDispatcher->createObject (); // empty array
225
+ }
119
226
120
- PgArrayHeader* arr = (PgArrayHeader*) data.data ;
121
- arr->size = (v_int32) htonl (arr->size );
122
- arr->oid = (v_int32) htonl (arr->oid );
123
- p_char8 payload = (p_char8) &data.data [sizeof (PgArrayHeader)];
227
+ ArrayDeserializationMeta meta;
228
+ meta._this = _this;
229
+ meta.data = &data;
124
230
125
- for (v_int32 i = 0 ; i < arr->size ; i ++) {
231
+ meta.arrayHeader = *((PgArrayHeader*) data.data );
232
+ meta.arrayHeader .ndim = (v_int32) htonl (meta.arrayHeader .ndim );
233
+ meta.arrayHeader .size = (v_int32) htonl (meta.arrayHeader .size );
234
+ meta.arrayHeader .oid = (v_int32) htonl (meta.arrayHeader .oid );
235
+ meta.arrayHeader .index = (v_int32) htonl (meta.arrayHeader .index );
126
236
127
- InData itemData;
128
- itemData.typeResolver = data.typeResolver ;
129
- itemData.size = (v_int32)ntohl (*((p_int32) payload));
130
- itemData.data = (const char *) (payload + sizeof (v_int32));
131
- itemData.oid = arr->oid ;
132
- itemData.isNull = itemData.size < 0 ;
237
+ meta.dimensions = {meta.arrayHeader .size };
133
238
134
- if (itemData.size > 0 ) {
135
- payload += sizeof (v_int32) + itemData.size ;
136
- } else {
137
- payload += sizeof (v_int32);
239
+ if (meta.arrayHeader .ndim == 1 ) {
240
+ meta.payload = (p_char8) &data.data [sizeof (PgArrayHeader)];
241
+ } else {
242
+ for (v_int32 i = 0 ; i < meta.arrayHeader .ndim - 1 ; i ++) {
243
+ v_int32 dsize = htonl ( * ((p_int32) &data.data [sizeof (PgArrayHeader) + i * sizeof (v_int32) * 2 ]));
244
+ meta.dimensions .push_back (dsize);
138
245
}
139
-
140
- const auto & item = _this->deserialize (itemData, itemType);
141
-
142
- polymorphicDispatcher->addPolymorphicItem (listWrapper, item);
143
-
246
+ meta.payload = (p_char8) &data.data [sizeof (PgArrayHeader) + sizeof (v_int32) * (meta.arrayHeader .ndim - 1 ) * 2 ];
144
247
}
145
248
146
- return oatpp::Void (listWrapper.getPtr (), listWrapper.valueType );
249
+ // for(v_int32 d : meta.dimensions) {
250
+ // OATPP_LOGD("Array", "D=%d", d);
251
+ // }
252
+
253
+ return deserializeSubArray (type, meta, 0 );
147
254
148
255
}
149
256
0 commit comments