@@ -96,7 +96,7 @@ template <typename M> static ERL_NIF_TERM strings_from_buffer(
96
96
return enif_make_list_from_array (env, values.data (), (unsigned )values.size ());
97
97
}
98
98
99
- static ERL_NIF_TERM arrow_array_to_nif_term (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level);
99
+ static int arrow_array_to_nif_term (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level, std::vector<ERL_NIF_TERM> &out_terms, ERL_NIF_TERM &error );
100
100
101
101
static int get_arrow_array_children_as_list (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level, std::vector<ERL_NIF_TERM> &children, ERL_NIF_TERM &error) {
102
102
ERL_NIF_TERM children_term{};
@@ -118,10 +118,18 @@ static int get_arrow_array_children_as_list(ErlNifEnv *env, struct ArrowSchema *
118
118
for (int64_t child_i = 0 ; child_i < schema->n_children ; child_i++) {
119
119
struct ArrowSchema * child_schema = schema->children [child_i];
120
120
struct ArrowArray * child_values = values->children [child_i];
121
- children[child_i] = arrow_array_to_nif_term (env, child_schema, child_values, level + 1 );
121
+ std::vector<ERL_NIF_TERM> childrens;
122
+ if (arrow_array_to_nif_term (env, child_schema, child_values, level + 1 , childrens, error) == 1 ) {
123
+ return 1 ;
124
+ }
125
+
126
+ if (childrens.size () == 0 ) {
127
+ children[child_i] = childrens[0 ];
128
+ } else {
129
+ children[child_i] = enif_make_tuple2 (env, childrens[0 ], childrens[1 ]);
130
+ }
122
131
}
123
132
}
124
- // children_term = enif_make_list_from_array(env, children.data(), (unsigned)schema->n_children);
125
133
126
134
return 0 ;
127
135
}
@@ -142,7 +150,7 @@ static ERL_NIF_TERM get_arrow_array_map_children(ErlNifEnv *env, struct ArrowSch
142
150
if (values->children == nullptr ) {
143
151
return erlang::nif::error (env, " invalid ArrowArray (map), values->children == nullptr" );
144
152
}
145
- if (schema ->n_children != 1 ) {
153
+ if (values ->n_children != 1 ) {
146
154
return erlang::nif::error (env, " invalid ArrowArray (map), values->n_children != 1" );
147
155
}
148
156
@@ -152,7 +160,6 @@ static ERL_NIF_TERM get_arrow_array_map_children(ErlNifEnv *env, struct ArrowSch
152
160
return erlang::nif::error (env, " invalid ArrowSchema (map), its single child is not named entries" );
153
161
}
154
162
155
- printf (" entries_values->n_children: %d\r\n " , entries_values->n_children );
156
163
std::vector<ERL_NIF_TERM> nif_keys, nif_values;
157
164
bool failed = false ;
158
165
for (int64_t child_i = 0 ; child_i < entries_values->n_children ; child_i++) {
@@ -177,7 +184,7 @@ static ERL_NIF_TERM get_arrow_array_map_children(ErlNifEnv *env, struct ArrowSch
177
184
178
185
if (!failed) {
179
186
if (nif_keys.size () != nif_values.size ()) {
180
- return erlang::nif::error (env, " map contains duplicated keys" );
187
+ return erlang::nif::error (env, " number of keys and values doesn't match " );
181
188
}
182
189
183
190
if (!enif_make_map_from_arrays (env, nif_keys.data (), nif_values.data (), (unsigned )nif_keys.size (), &map_out)) {
@@ -190,18 +197,100 @@ static ERL_NIF_TERM get_arrow_array_map_children(ErlNifEnv *env, struct ArrowSch
190
197
}
191
198
}
192
199
193
- ERL_NIF_TERM arrow_array_to_nif_term (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level) {
200
+ static ERL_NIF_TERM get_arrow_array_union_children (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level) {
201
+ ERL_NIF_TERM error{}, map_out{};
202
+ if (schema->n_children > 0 && schema->children == nullptr ) {
203
+ return erlang::nif::error (env, " invalid ArrowSchema (union), schema->children == nullptr while schema->n_children > 0 " );
204
+ }
205
+ if (values->n_children > 0 && values->children == nullptr ) {
206
+ return erlang::nif::error (env, " invalid ArrowArray (union), values->children == nullptr while values->n_children > 0" );
207
+ }
208
+
209
+ std::vector<ERL_NIF_TERM> nif_keys (values->n_children ), nif_values2 (values->n_children );
210
+ std::vector<ERL_NIF_TERM> field_values;
211
+ bool failed = false ;
212
+ for (int64_t child_i = 0 ; child_i < values->n_children ; child_i++) {
213
+ struct ArrowSchema * entry_schema = schema->children [child_i];
214
+ struct ArrowArray * entry_values = values->children [child_i];
215
+ nif_keys[child_i] = erlang::nif::make_binary (env, entry_schema->name );
216
+ if (arrow_array_to_nif_term (env, entry_schema, entry_values, level + 1 , field_values, error) == 1 ) {
217
+ return error;
218
+ }
219
+
220
+ if (field_values.size () == 0 ) {
221
+ nif_values2[child_i] = field_values[0 ];
222
+ } else {
223
+ nif_values2[child_i] = field_values[1 ];
224
+ }
225
+ }
226
+
227
+ if (!failed) {
228
+ if (!enif_make_map_from_arrays (env, nif_keys.data (), nif_values2.data (), (unsigned )nif_keys.size (), &map_out)) {
229
+ return erlang::nif::error (env, " union contains duplicated fields" );
230
+ } else {
231
+ return map_out;
232
+ }
233
+ } else {
234
+ return erlang::nif::error (env, " invalid union" );
235
+ }
236
+ }
237
+
238
+ static ERL_NIF_TERM get_arrow_array_list_children (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level) {
239
+ ERL_NIF_TERM error{};
240
+ if (schema->children == nullptr ) {
241
+ return erlang::nif::error (env, " invalid ArrowSchema (list), schema->children == nullptr" );
242
+ }
243
+ if (schema->n_children != 1 ) {
244
+ return erlang::nif::error (env, " invalid ArrowSchema (list), schema->n_children != 1" );
245
+ }
246
+ if (values->children == nullptr ) {
247
+ return erlang::nif::error (env, " invalid ArrowArray (list), values->children == nullptr" );
248
+ }
249
+ if (values->n_children != 1 ) {
250
+ return erlang::nif::error (env, " invalid ArrowArray (list), values->n_children != 1" );
251
+ }
252
+
253
+ struct ArrowSchema * items_schema = schema->children [0 ];
254
+ struct ArrowArray * items_values = values->children [0 ];
255
+ if (strncmp (" item" , items_schema->name , 4 ) != 0 ) {
256
+ return erlang::nif::error (env, " invalid ArrowSchema (list), its single child is not named item" );
257
+ }
258
+
259
+ std::vector<ERL_NIF_TERM> children (items_values->n_children );
260
+ bool failed = false ;
261
+ for (int64_t child_i = 0 ; child_i < items_values->n_children ; child_i++) {
262
+ struct ArrowSchema * item_schema = items_schema->children [child_i];
263
+ struct ArrowArray * item_values = items_values->children [child_i];
264
+
265
+ std::vector<ERL_NIF_TERM> childrens;
266
+ if (arrow_array_to_nif_term (env, item_schema, item_values, level + 1 , childrens, error) == 1 ) {
267
+ return error;
268
+ }
269
+
270
+ if (childrens.size () == 0 ) {
271
+ children[child_i] = childrens[0 ];
272
+ } else {
273
+ children[child_i] = enif_make_tuple2 (env, childrens[0 ], childrens[1 ]);
274
+ }
275
+ }
276
+
277
+ return enif_make_list_from_array (env, children.data (), (unsigned )items_values->n_children );
278
+ }
279
+
280
+ int arrow_array_to_nif_term (ErlNifEnv *env, struct ArrowSchema * schema, struct ArrowArray * values, uint64_t level, std::vector<ERL_NIF_TERM> &out_terms, ERL_NIF_TERM &error) {
194
281
if (schema == nullptr ) {
195
- return erlang::nif::error (env, " invalid ArrowSchema (nullptr) when invoking next" );
282
+ error = erlang::nif::error (env, " invalid ArrowSchema (nullptr) when invoking next" );
283
+ return 1 ;
196
284
}
197
285
if (values == nullptr ) {
198
- return erlang::nif::error (env, " invalid ArrowArray (nullptr) when invoking next" );
286
+ error = erlang::nif::error (env, " invalid ArrowArray (nullptr) when invoking next" );
287
+ return 1 ;
199
288
}
200
289
201
290
const char * format = schema->format ? schema->format : " " ;
202
291
const char * name = schema->name ? schema->name : " " ;
203
292
204
- ERL_NIF_TERM current_term{}, children_term{}, error{} ;
293
+ ERL_NIF_TERM current_term{}, children_term{};
205
294
std::vector<ERL_NIF_TERM> children;
206
295
207
296
bool has_validity_bitmap = values->null_count != 0 && values->null_count != -1 ;
@@ -342,39 +431,21 @@ ERL_NIF_TERM arrow_array_to_nif_term(ErlNifEnv *env, struct ArrowSchema * schema
342
431
// only handle and return children if this is a struct
343
432
is_struct = true ;
344
433
if (get_arrow_array_children_as_list (env, schema, values, level, children, error) == 1 ) {
345
- return error ;
434
+ return 1 ;
346
435
}
347
436
children_term = enif_make_list_from_array (env, children.data (), (unsigned )schema->n_children );
348
- // get_arrow_array_children_as_list(env, schema, values, level, children, error);
349
437
} else if (strncmp (" +m" , format, 2 ) == 0 ) {
350
- // if (get_arrow_array_children_as_list(env, schema, values, level, children, error) == 1) {
351
- // return error;
352
- // }
353
- // children_term = enif_make_list_from_array(env, children.data(), (unsigned)schema->n_children);
354
438
children_term = get_arrow_array_map_children (env, schema, values, level);
355
439
} else if (strncmp (" +l" , format, 2 ) == 0 || strncmp (" +L" , format, 2 ) == 0 ) {
356
- if (get_arrow_array_children_as_list (env, schema, values, level, children, error) == 1 ) {
357
- return error;
358
- }
359
- children_term = enif_make_list_from_array (env, children.data (), (unsigned )schema->n_children );
360
- // children_term = get_arrow_array_children_as_list(env, schema, values, level);
440
+ children_term = get_arrow_array_list_children (env, schema, values, level);
361
441
} else {
362
442
format_processed = false ;
363
443
}
364
444
} else if (format_len >= 4 ) {
365
445
if (strncmp (" +w:" , format, 3 ) == 0 ) {
366
- if (get_arrow_array_children_as_list (env, schema, values, level, children, error) == 1 ) {
367
- return error;
368
- }
369
- children_term = enif_make_list_from_array (env, children.data (), (unsigned )schema->n_children );
370
- // children_term = get_arrow_array_children_as_list(env, schema, values, level);
446
+ children_term = get_arrow_array_list_children (env, schema, values, level);
371
447
} else if (format_len > 4 && (strncmp (" +ud:" , format, 4 ) == 0 || strncmp (" +us:" , format, 4 ) == 0 )) {
372
- // todo: get as map
373
- if (get_arrow_array_children_as_list (env, schema, values, level, children, error) == 1 ) {
374
- return error;
375
- }
376
- children_term = enif_make_list_from_array (env, children.data (), (unsigned )schema->n_children );
377
- // children_term = get_arrow_array_children_as_list(env, schema, values, level);
448
+ children_term = get_arrow_array_union_children (env, schema, values, level);
378
449
} else {
379
450
format_processed = false ;
380
451
}
@@ -395,21 +466,21 @@ ERL_NIF_TERM arrow_array_to_nif_term(ErlNifEnv *env, struct ArrowSchema * schema
395
466
// printf("buffers: %p\r\n", values->buffers);
396
467
}
397
468
469
+ out_terms.clear ();
470
+
398
471
if (is_struct) {
399
- return children_term;
472
+ out_terms. emplace_back ( children_term) ;
400
473
} else {
401
474
if (schema->children ) {
402
- return enif_make_tuple2 (env,
403
- erlang::nif::make_binary (env, name),
404
- children_term
405
- );
475
+ out_terms.emplace_back (erlang::nif::make_binary (env, name));
476
+ out_terms.emplace_back (children_term);
406
477
} else {
407
- return enif_make_tuple2 (env,
408
- erlang::nif::make_binary (env, name),
409
- current_term
410
- );
478
+ out_terms.emplace_back (erlang::nif::make_binary (env, name));
479
+ out_terms.emplace_back (current_term);
411
480
}
412
481
}
482
+
483
+ return 0 ;
413
484
}
414
485
415
486
static ERL_NIF_TERM adbc_database_new (ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) {
@@ -804,8 +875,19 @@ static ERL_NIF_TERM adbc_arrow_array_stream_next(ErlNifEnv *env, int argc, const
804
875
}
805
876
}
806
877
878
+ std::vector<ERL_NIF_TERM> out_terms;
879
+
807
880
auto schema = (struct ArrowSchema *)res->private_data ;
808
- ret = arrow_array_to_nif_term (env, schema, &out, 0 );
881
+ if (arrow_array_to_nif_term (env, schema, &out, 0 , out_terms, error) == 1 ) {
882
+ if (out.release ) out.release (&out);
883
+ return error;
884
+ }
885
+
886
+ if (out_terms.size () == 1 ) {
887
+ ret = out_terms[0 ];
888
+ } else {
889
+ ret = enif_make_tuple2 (env, out_terms[0 ], out_terms[1 ]);
890
+ }
809
891
810
892
if (out.release ) {
811
893
out.release (&out);
0 commit comments