nanoarrow 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/ext/nanoarrow/array.c +1 -0
- data/ext/nanoarrow/array_builder.c +164 -0
- data/ext/nanoarrow/array_view.c +69 -0
- data/ext/nanoarrow/capsule.c +4 -1
- data/ext/nanoarrow/schema.c +71 -5
- data/ext/nanoarrow/schema_builder.c +100 -0
- data/lib/nanoarrow/array_builder.rb +28 -1
- data/lib/nanoarrow/iterator.rb +35 -4
- data/lib/nanoarrow/schema.rb +13 -1
- data/lib/nanoarrow/types.rb +12 -6
- data/lib/nanoarrow/utils.rb +43 -7
- data/lib/nanoarrow/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a01c23d857a3993f98281df9c297cc68e27550cdd19eff8844dc088389e73375
|
|
4
|
+
data.tar.gz: 272666407eaab6685a2739e4e318a9f17df6f3284a2b5438cd5a6729d9ca6345
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 86fcf358b4353c6b7047907a691c0742e3404c0030f7f486bd60295746c8ac6ede47630cbb4d88585166f1ac5e900ad9be688952613251efbeca26027746202c
|
|
7
|
+
data.tar.gz: cc2e9133a58184ec28159268840d5831eec8b2fd445986da2f36b2c7743ffa567e581979771f4294481ff9af82e2c504d6358d5856ef3cf0d679b3b103f61e29
|
data/CHANGELOG.md
CHANGED
data/ext/nanoarrow/array.c
CHANGED
|
@@ -94,6 +94,7 @@ void Init_array(void)
|
|
|
94
94
|
rb_define_alloc_func(cCArray, array_allocate);
|
|
95
95
|
rb_define_method(cCArray, "schema", array_schema, 0);
|
|
96
96
|
rb_define_method(cCArray, "valid?", array_is_valid, 0);
|
|
97
|
+
rb_define_method(cCArray, "assert_valid", array_assert_valid, 0);
|
|
97
98
|
rb_define_method(cCArray, "length", array_length, 0);
|
|
98
99
|
rb_define_method(cCArray, "child", array_child, 1);
|
|
99
100
|
}
|
|
@@ -231,6 +231,164 @@ static VALUE array_builder_append_bytes(VALUE self, VALUE obj)
|
|
|
231
231
|
return self;
|
|
232
232
|
}
|
|
233
233
|
|
|
234
|
+
static VALUE array_builder_append_decimals(VALUE self, VALUE obj, VALUE bitwidth, VALUE precision, VALUE scale)
|
|
235
|
+
{
|
|
236
|
+
array_builder_t* builder;
|
|
237
|
+
GetArrayBuilder(self, builder);
|
|
238
|
+
|
|
239
|
+
int pi = NUM2INT(precision);
|
|
240
|
+
int si = NUM2INT(scale);
|
|
241
|
+
VALUE pad = rb_str_new_cstr("0");
|
|
242
|
+
|
|
243
|
+
struct ArrowDecimal decimal;
|
|
244
|
+
ArrowDecimalInit(&decimal, NUM2INT(bitwidth), pi, si);
|
|
245
|
+
|
|
246
|
+
Check_Type(obj, T_ARRAY);
|
|
247
|
+
|
|
248
|
+
for (long i = 0; i < RARRAY_LEN(obj); i++)
|
|
249
|
+
{
|
|
250
|
+
VALUE v = rb_ary_entry(obj, i);
|
|
251
|
+
int code;
|
|
252
|
+
|
|
253
|
+
if (NIL_P(v))
|
|
254
|
+
code = ArrowArrayAppendNull(builder->ptr, 1);
|
|
255
|
+
else
|
|
256
|
+
{
|
|
257
|
+
VALUE split = rb_funcall(v, rb_intern("split"), 0);
|
|
258
|
+
VALUE sign = rb_ary_entry(split, 0);
|
|
259
|
+
VALUE digits = rb_ary_entry(split, 1);
|
|
260
|
+
VALUE base = rb_ary_entry(split, 2);
|
|
261
|
+
VALUE exponent = rb_ary_entry(split, 3);
|
|
262
|
+
|
|
263
|
+
if (NUM2INT(base) != 10)
|
|
264
|
+
raise_todo();
|
|
265
|
+
|
|
266
|
+
Check_Type(digits, T_STRING);
|
|
267
|
+
|
|
268
|
+
// exceeds precision
|
|
269
|
+
// TODO better error
|
|
270
|
+
if (RSTRING_LEN(digits) > pi)
|
|
271
|
+
raise_todo();
|
|
272
|
+
|
|
273
|
+
int target = si + NUM2INT(exponent);
|
|
274
|
+
|
|
275
|
+
// exceeds scale
|
|
276
|
+
// TODO either round in Ruby or better error
|
|
277
|
+
if (RSTRING_LEN(digits) > target)
|
|
278
|
+
raise_todo();
|
|
279
|
+
|
|
280
|
+
digits = rb_funcall(digits, rb_intern("ljust"), 2, INT2NUM(target), pad);
|
|
281
|
+
|
|
282
|
+
struct ArrowStringView sv;
|
|
283
|
+
sv.data = StringValuePtr(digits);
|
|
284
|
+
sv.size_bytes = RSTRING_LEN(digits);
|
|
285
|
+
code = ArrowDecimalSetDigits(&decimal, sv);
|
|
286
|
+
raise_error_not_ok("ArrowDecimalSetDigits()", code);
|
|
287
|
+
|
|
288
|
+
if (NUM2INT(sign) == -1)
|
|
289
|
+
ArrowDecimalNegate(&decimal);
|
|
290
|
+
|
|
291
|
+
code = ArrowArrayAppendDecimal(builder->ptr, &decimal);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
raise_error_not_ok("ArrowArrayAppendDecimal()", code);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
return self;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
static VALUE array_builder_set_offset(VALUE self, VALUE offset)
|
|
301
|
+
{
|
|
302
|
+
array_builder_t* builder;
|
|
303
|
+
GetArrayBuilder(self, builder);
|
|
304
|
+
|
|
305
|
+
rb_funcall(builder->c_array, rb_intern("assert_valid"), 0);
|
|
306
|
+
builder->ptr->offset = NUM2LL(offset);
|
|
307
|
+
return self;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
static VALUE array_builder_set_length(VALUE self, VALUE length)
|
|
311
|
+
{
|
|
312
|
+
array_builder_t* builder;
|
|
313
|
+
GetArrayBuilder(self, builder);
|
|
314
|
+
|
|
315
|
+
rb_funcall(builder->c_array, rb_intern("assert_valid"), 0);
|
|
316
|
+
builder->ptr->length = NUM2LL(length);
|
|
317
|
+
return self;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
static VALUE array_builder_set_null_count(VALUE self, VALUE null_count)
|
|
321
|
+
{
|
|
322
|
+
array_builder_t* builder;
|
|
323
|
+
GetArrayBuilder(self, builder);
|
|
324
|
+
|
|
325
|
+
rb_funcall(builder->c_array, rb_intern("assert_valid"), 0);
|
|
326
|
+
builder->ptr->null_count = NUM2LL(null_count);
|
|
327
|
+
return self;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
static VALUE array_builder_resolve_null_count(VALUE self)
|
|
331
|
+
{
|
|
332
|
+
array_builder_t* builder;
|
|
333
|
+
GetArrayBuilder(self, builder);
|
|
334
|
+
|
|
335
|
+
rb_funcall(builder->c_array, rb_intern("assert_valid"), 0);
|
|
336
|
+
|
|
337
|
+
VALUE format = rb_funcall(rb_funcall(builder->c_array, rb_intern("schema"), 0), rb_intern("format"), 0);
|
|
338
|
+
if (RTEST(rb_funcall(format, rb_intern("start_with?"), 1, rb_str_new_cstr("+us:"))) || RTEST(rb_funcall(format, rb_intern("start_with?"), 1, rb_str_new_cstr("+ud:"))))
|
|
339
|
+
return self;
|
|
340
|
+
|
|
341
|
+
if (builder->ptr->null_count != -1)
|
|
342
|
+
return self;
|
|
343
|
+
|
|
344
|
+
struct ArrowBuffer* validity_buffer = ArrowArrayBuffer(builder->ptr, 0);
|
|
345
|
+
if (validity_buffer->size_bytes == 0)
|
|
346
|
+
{
|
|
347
|
+
builder->ptr->null_count = 0;
|
|
348
|
+
return self;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
int64_t bits = builder->ptr->offset + builder->ptr->length;
|
|
352
|
+
int64_t bytes_required = (bits >> 3) + ((bits & 7) != 0);
|
|
353
|
+
|
|
354
|
+
if (validity_buffer->size_bytes < bytes_required)
|
|
355
|
+
rb_raise(rb_eArgError, "validity bitmap mismatch");
|
|
356
|
+
|
|
357
|
+
int64_t count = ArrowBitCountSet(
|
|
358
|
+
validity_buffer->data,
|
|
359
|
+
builder->ptr->offset,
|
|
360
|
+
builder->ptr->length
|
|
361
|
+
);
|
|
362
|
+
builder->ptr->null_count = builder->ptr->length - count;
|
|
363
|
+
|
|
364
|
+
return self;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
static VALUE array_builder_set_child(VALUE self, VALUE idx, VALUE c_array)
|
|
368
|
+
{
|
|
369
|
+
array_builder_t* builder;
|
|
370
|
+
GetArrayBuilder(self, builder);
|
|
371
|
+
|
|
372
|
+
array_t* c_array_ptr;
|
|
373
|
+
GetArray(c_array, c_array_ptr);
|
|
374
|
+
|
|
375
|
+
VALUE child = rb_funcall(builder->c_array, rb_intern("child"), 1, idx);
|
|
376
|
+
array_t* child_ptr;
|
|
377
|
+
GetArray(child, child_ptr);
|
|
378
|
+
if (child_ptr->ptr->release != NULL)
|
|
379
|
+
ArrowArrayRelease(child_ptr->ptr);
|
|
380
|
+
|
|
381
|
+
// TODO move to parameter
|
|
382
|
+
VALUE move = Qfalse;
|
|
383
|
+
|
|
384
|
+
if (!RTEST(move))
|
|
385
|
+
c_array_shallow_copy(c_array_ptr->base, c_array_ptr->ptr, child_ptr->ptr);
|
|
386
|
+
else
|
|
387
|
+
ArrowArrayMove(c_array_ptr->ptr, child_ptr->ptr);
|
|
388
|
+
|
|
389
|
+
return self;
|
|
390
|
+
}
|
|
391
|
+
|
|
234
392
|
static VALUE array_builder_finish(VALUE self)
|
|
235
393
|
{
|
|
236
394
|
array_builder_t* builder;
|
|
@@ -264,5 +422,11 @@ void Init_array_builder(void)
|
|
|
264
422
|
rb_define_method(cCArrayBuilder, "append_doubles", array_builder_append_doubles, 1);
|
|
265
423
|
rb_define_method(cCArrayBuilder, "append_strings", array_builder_append_strings, 1);
|
|
266
424
|
rb_define_method(cCArrayBuilder, "append_bytes", array_builder_append_bytes, 1);
|
|
425
|
+
rb_define_method(cCArrayBuilder, "append_decimals", array_builder_append_decimals, 4);
|
|
426
|
+
rb_define_method(cCArrayBuilder, "set_offset", array_builder_set_offset, 1);
|
|
427
|
+
rb_define_method(cCArrayBuilder, "set_length", array_builder_set_length, 1);
|
|
428
|
+
rb_define_method(cCArrayBuilder, "set_null_count", array_builder_set_null_count, 1);
|
|
429
|
+
rb_define_method(cCArrayBuilder, "resolve_null_count", array_builder_resolve_null_count, 0);
|
|
430
|
+
rb_define_method(cCArrayBuilder, "set_child", array_builder_set_child, 2);
|
|
267
431
|
rb_define_method(cCArrayBuilder, "finish", array_builder_finish, 0);
|
|
268
432
|
}
|
data/ext/nanoarrow/array_view.c
CHANGED
|
@@ -76,6 +76,41 @@ static VALUE array_view_set_array(VALUE self, VALUE array)
|
|
|
76
76
|
return self;
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
+
static VALUE array_view_n_children(VALUE self)
|
|
80
|
+
{
|
|
81
|
+
array_view_t* view;
|
|
82
|
+
GetArrayView(self, view);
|
|
83
|
+
|
|
84
|
+
return LL2NUM(view->ptr->n_children);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
static VALUE array_view_child(VALUE self, VALUE idx)
|
|
88
|
+
{
|
|
89
|
+
array_view_t* view;
|
|
90
|
+
GetArrayView(self, view);
|
|
91
|
+
|
|
92
|
+
int64_t i = NUM2LL(idx);
|
|
93
|
+
if (i < 0 || i >= view->ptr->n_children)
|
|
94
|
+
rb_raise(rb_eIndexError, "out of range");
|
|
95
|
+
|
|
96
|
+
VALUE child = array_view_allocate(cCArrayView);
|
|
97
|
+
array_view_t* child_ptr;
|
|
98
|
+
GetArrayView(child, child_ptr);
|
|
99
|
+
child_ptr->base = view->base;
|
|
100
|
+
child_ptr->ptr = view->ptr->children[i];
|
|
101
|
+
|
|
102
|
+
return child;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
static VALUE array_view_children(VALUE self)
|
|
106
|
+
{
|
|
107
|
+
int64_t n_children = NUM2LL(array_view_n_children(self));
|
|
108
|
+
VALUE children = rb_ary_new();
|
|
109
|
+
for (int64_t i = 0; i < n_children; i++)
|
|
110
|
+
rb_ary_push(children, array_view_child(self, LL2NUM(i)));
|
|
111
|
+
return children;
|
|
112
|
+
}
|
|
113
|
+
|
|
79
114
|
static VALUE array_view_each_bool(VALUE self)
|
|
80
115
|
{
|
|
81
116
|
array_view_t* view;
|
|
@@ -162,16 +197,50 @@ static VALUE array_view_each_binary(VALUE self)
|
|
|
162
197
|
return self;
|
|
163
198
|
}
|
|
164
199
|
|
|
200
|
+
static VALUE array_view_each_decimal(VALUE self, VALUE bitwidth, VALUE precision, VALUE scale)
|
|
201
|
+
{
|
|
202
|
+
array_view_t* view;
|
|
203
|
+
GetArrayView(self, view);
|
|
204
|
+
|
|
205
|
+
struct ArrowDecimal decimal;
|
|
206
|
+
ArrowDecimalInit(&decimal, NUM2INT(bitwidth), NUM2INT(precision), NUM2INT(scale));
|
|
207
|
+
|
|
208
|
+
struct ArrowBuffer buffer;
|
|
209
|
+
ArrowBufferInit(&buffer);
|
|
210
|
+
|
|
211
|
+
for (int64_t i = 0; i < view->ptr->length; i++)
|
|
212
|
+
{
|
|
213
|
+
VALUE v;
|
|
214
|
+
if (ArrowArrayViewIsNull(view->ptr, i))
|
|
215
|
+
v = Qnil;
|
|
216
|
+
else
|
|
217
|
+
{
|
|
218
|
+
ArrowArrayViewGetDecimalUnsafe(view->ptr, i, &decimal);
|
|
219
|
+
int code = ArrowDecimalAppendStringToBuffer(&decimal, &buffer);
|
|
220
|
+
raise_error_not_ok("ArrowDecimalAppendStringToBuffer()", code);
|
|
221
|
+
v = rb_str_new((char*) buffer.data, buffer.size_bytes);
|
|
222
|
+
ArrowBufferReset(&buffer);
|
|
223
|
+
}
|
|
224
|
+
rb_yield(v);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return self;
|
|
228
|
+
}
|
|
229
|
+
|
|
165
230
|
void Init_array_view(void)
|
|
166
231
|
{
|
|
167
232
|
cCArrayView = rb_define_class_under(mNanoarrow, "CArrayView", rb_cObject);
|
|
168
233
|
rb_define_alloc_func(cCArrayView, array_view_allocate);
|
|
169
234
|
rb_define_singleton_method(cCArrayView, "from_schema", array_view_from_schema, 1);
|
|
170
235
|
rb_define_method(cCArrayView, "set_array", array_view_set_array, 1);
|
|
236
|
+
rb_define_method(cCArrayView, "n_children", array_view_n_children, 0);
|
|
237
|
+
rb_define_method(cCArrayView, "child", array_view_child, 1);
|
|
238
|
+
rb_define_method(cCArrayView, "children", array_view_children, 0);
|
|
171
239
|
rb_define_method(cCArrayView, "each_bool", array_view_each_bool, 0);
|
|
172
240
|
rb_define_method(cCArrayView, "each_int", array_view_each_int, 0);
|
|
173
241
|
rb_define_method(cCArrayView, "each_uint", array_view_each_uint, 0);
|
|
174
242
|
rb_define_method(cCArrayView, "each_double", array_view_each_double, 0);
|
|
175
243
|
rb_define_method(cCArrayView, "each_string", array_view_each_string, 0);
|
|
176
244
|
rb_define_method(cCArrayView, "each_binary", array_view_each_binary, 0);
|
|
245
|
+
rb_define_method(cCArrayView, "each_decimal", array_view_each_decimal, 3);
|
|
177
246
|
}
|
data/ext/nanoarrow/capsule.c
CHANGED
|
@@ -77,7 +77,10 @@ static VALUE capsule_name(VALUE self)
|
|
|
77
77
|
capsule_t* capsule;
|
|
78
78
|
GetCapsule(self, capsule);
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
if (capsule->name != NULL)
|
|
81
|
+
return rb_utf8_str_new_cstr(capsule->name);
|
|
82
|
+
else
|
|
83
|
+
return Qnil;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
void Init_capsule(void)
|
data/ext/nanoarrow/schema.c
CHANGED
|
@@ -227,6 +227,15 @@ static VALUE schema_child(VALUE self, VALUE rb_i)
|
|
|
227
227
|
return obj;
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
static VALUE schema_children(VALUE self)
|
|
231
|
+
{
|
|
232
|
+
int64_t n_children = NUM2LL(schema_n_children(self));
|
|
233
|
+
VALUE children = rb_ary_new();
|
|
234
|
+
for (int64_t i = 0; i < n_children; i++)
|
|
235
|
+
rb_ary_push(children, schema_child(self, LL2NUM(i)));
|
|
236
|
+
return children;
|
|
237
|
+
}
|
|
238
|
+
|
|
230
239
|
static VALUE schema_dictionary(VALUE self)
|
|
231
240
|
{
|
|
232
241
|
schema_t* schema;
|
|
@@ -273,8 +282,41 @@ static VALUE schema_arrow_c_schema(VALUE self)
|
|
|
273
282
|
return schema_capsule;
|
|
274
283
|
}
|
|
275
284
|
|
|
276
|
-
static VALUE schema_modify(
|
|
285
|
+
static VALUE schema_modify(int argc, VALUE* argv, VALUE self)
|
|
277
286
|
{
|
|
287
|
+
VALUE kwargs;
|
|
288
|
+
rb_scan_args(argc, argv, "0:", &kwargs);
|
|
289
|
+
|
|
290
|
+
ID keywords[8];
|
|
291
|
+
VALUE values[8];
|
|
292
|
+
keywords[0] = rb_intern("format");
|
|
293
|
+
keywords[1] = rb_intern("name");
|
|
294
|
+
keywords[2] = rb_intern("flags");
|
|
295
|
+
keywords[3] = rb_intern("nullable");
|
|
296
|
+
keywords[4] = rb_intern("metadata");
|
|
297
|
+
keywords[5] = rb_intern("children");
|
|
298
|
+
keywords[6] = rb_intern("dictionary");
|
|
299
|
+
keywords[7] = rb_intern("validate");
|
|
300
|
+
rb_get_kwargs(kwargs, keywords, 0, 8, values);
|
|
301
|
+
|
|
302
|
+
for (int i = 0; i < 8; i++)
|
|
303
|
+
{
|
|
304
|
+
if (values[i] == Qundef)
|
|
305
|
+
values[i] = Qnil;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
VALUE format = values[0];
|
|
309
|
+
VALUE name = values[1];
|
|
310
|
+
VALUE flags = values[2];
|
|
311
|
+
VALUE nullable = values[3];
|
|
312
|
+
VALUE metadata = values[4];
|
|
313
|
+
VALUE children = values[5];
|
|
314
|
+
VALUE dictionary = values[6];
|
|
315
|
+
VALUE validate = values[7];
|
|
316
|
+
|
|
317
|
+
if (NIL_P(validate))
|
|
318
|
+
validate = Qtrue;
|
|
319
|
+
|
|
278
320
|
VALUE builder = rb_funcall(cCSchemaBuilder, rb_intern("allocate"), 0);
|
|
279
321
|
|
|
280
322
|
if (NIL_P(format))
|
|
@@ -306,11 +348,34 @@ static VALUE schema_modify(VALUE self, VALUE format, VALUE name, VALUE flags, VA
|
|
|
306
348
|
|
|
307
349
|
if (NIL_P(children))
|
|
308
350
|
{
|
|
309
|
-
|
|
310
|
-
|
|
351
|
+
int64_t n_children = NUM2LL(rb_funcall(self, rb_intern("n_children"), 0));
|
|
352
|
+
if (n_children > 0)
|
|
353
|
+
{
|
|
354
|
+
rb_funcall(builder, rb_intern("allocate_children"), 1, LL2NUM(n_children));
|
|
355
|
+
VALUE self_children = rb_funcall(self, rb_intern("children"), 0);
|
|
356
|
+
for (long i = 0; i < RARRAY_LEN(self_children); i++)
|
|
357
|
+
rb_funcall(builder, rb_intern("set_child"), 3, LONG2NUM(i), Qnil, rb_ary_entry(self_children, i));
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
else if (RB_TYPE_P(children, T_HASH))
|
|
361
|
+
{
|
|
362
|
+
// not as efficient as rb_hash_foreach, but simpler
|
|
363
|
+
VALUE keys = rb_funcall(children, rb_intern("keys"), 0);
|
|
364
|
+
Check_Type(keys, T_ARRAY);
|
|
365
|
+
rb_funcall(builder, rb_intern("allocate_children"), 1, LONG2NUM(RARRAY_LEN(keys)));
|
|
366
|
+
for (long i = 0; i < RARRAY_LEN(keys); i++)
|
|
367
|
+
{
|
|
368
|
+
VALUE key = rb_ary_entry(keys, i);
|
|
369
|
+
rb_funcall(builder, rb_intern("set_child"), 3, LONG2NUM(i), key, rb_hash_lookup(children, key));
|
|
370
|
+
}
|
|
311
371
|
}
|
|
312
372
|
else
|
|
313
|
-
|
|
373
|
+
{
|
|
374
|
+
Check_Type(children, T_ARRAY);
|
|
375
|
+
rb_funcall(builder, rb_intern("allocate_children"), 1, LONG2NUM(RARRAY_LEN(children)));
|
|
376
|
+
for (long i = 0; i < RARRAY_LEN(children); i++)
|
|
377
|
+
rb_funcall(builder, rb_intern("set_child"), 3, LONG2NUM(i), Qnil, rb_ary_entry(children, i));
|
|
378
|
+
}
|
|
314
379
|
|
|
315
380
|
if (NIL_P(dictionary))
|
|
316
381
|
{
|
|
@@ -338,9 +403,10 @@ void Init_schema(void)
|
|
|
338
403
|
rb_define_method(cCSchema, "metadata", schema_metadata, 0);
|
|
339
404
|
rb_define_method(cCSchema, "n_children", schema_n_children, 0);
|
|
340
405
|
rb_define_method(cCSchema, "child", schema_child, 1);
|
|
406
|
+
rb_define_method(cCSchema, "children", schema_children, 0);
|
|
341
407
|
rb_define_method(cCSchema, "dictionary", schema_dictionary, 0);
|
|
342
408
|
rb_define_method(cCSchema, "to_s", schema_to_s, 0);
|
|
343
409
|
rb_define_method(cCSchema, "arrow_c_schema", schema_arrow_c_schema, 0);
|
|
344
|
-
rb_define_method(cCSchema, "modify", schema_modify,
|
|
410
|
+
rb_define_method(cCSchema, "modify", schema_modify, -1);
|
|
345
411
|
rb_define_method(cCSchema, "assert_valid", schema_assert_valid, 0);
|
|
346
412
|
}
|
|
@@ -183,6 +183,75 @@ static VALUE schema_builder_set_name(VALUE self, VALUE name)
|
|
|
183
183
|
return self;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
+
static VALUE schema_builder_allocate_children(VALUE self, VALUE n)
|
|
187
|
+
{
|
|
188
|
+
schema_builder_t* builder;
|
|
189
|
+
GetSchemaBuilder(self, builder);
|
|
190
|
+
|
|
191
|
+
schema_assert_valid(builder->c_schema);
|
|
192
|
+
|
|
193
|
+
int code = ArrowSchemaAllocateChildren(builder->ptr, NUM2LL(n));
|
|
194
|
+
raise_error_not_ok("ArrowSchemaAllocateChildren()", code);
|
|
195
|
+
|
|
196
|
+
return self;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static VALUE schema_builder_set_child(VALUE self, VALUE idx, VALUE name, VALUE child_src)
|
|
200
|
+
{
|
|
201
|
+
schema_builder_t* builder;
|
|
202
|
+
GetSchemaBuilder(self, builder);
|
|
203
|
+
|
|
204
|
+
schema_assert_valid(builder->c_schema);
|
|
205
|
+
|
|
206
|
+
int64_t i = NUM2LL(idx);
|
|
207
|
+
if (i < 0 || i >= builder->ptr->n_children)
|
|
208
|
+
rb_raise(rb_eIndexError, "Index out of range");
|
|
209
|
+
|
|
210
|
+
if (builder->ptr->children[i]->release != NULL)
|
|
211
|
+
ArrowSchemaRelease(builder->ptr->children[i]);
|
|
212
|
+
|
|
213
|
+
schema_t* child_src_ptr;
|
|
214
|
+
GetSchema(child_src, child_src_ptr);
|
|
215
|
+
|
|
216
|
+
int code = ArrowSchemaDeepCopy(child_src_ptr->ptr, builder->ptr->children[i]);
|
|
217
|
+
raise_error_not_ok("ArrowSchemaDeepCopy()", code);
|
|
218
|
+
|
|
219
|
+
if (!NIL_P(name))
|
|
220
|
+
{
|
|
221
|
+
Check_Type(name, T_STRING);
|
|
222
|
+
code = ArrowSchemaSetName(builder->ptr->children[i], StringValueCStr(name));
|
|
223
|
+
raise_error_not_ok("ArrowSchemaSetName()", code);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return self;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
static VALUE schema_builder_set_dictionary(VALUE self, VALUE dictionary)
|
|
230
|
+
{
|
|
231
|
+
schema_builder_t* builder;
|
|
232
|
+
GetSchemaBuilder(self, builder);
|
|
233
|
+
|
|
234
|
+
schema_assert_valid(builder->c_schema);
|
|
235
|
+
|
|
236
|
+
int code;
|
|
237
|
+
if (builder->ptr->dictionary == NULL)
|
|
238
|
+
{
|
|
239
|
+
code = ArrowSchemaAllocateDictionary(builder->ptr);
|
|
240
|
+
raise_error_not_ok("ArrowSchemaAllocateDictionary()", code);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (builder->ptr->dictionary->release != NULL)
|
|
244
|
+
ArrowSchemaRelease(builder->ptr->dictionary);
|
|
245
|
+
|
|
246
|
+
schema_t* dictionary_ptr;
|
|
247
|
+
GetSchema(dictionary, dictionary_ptr);
|
|
248
|
+
|
|
249
|
+
code = ArrowSchemaDeepCopy(dictionary_ptr->ptr, builder->ptr->dictionary);
|
|
250
|
+
raise_error_not_ok("ArrowSchemaDeepCopy()", code);
|
|
251
|
+
|
|
252
|
+
return self;
|
|
253
|
+
}
|
|
254
|
+
|
|
186
255
|
static VALUE schema_builder_set_flags(VALUE self, VALUE flags)
|
|
187
256
|
{
|
|
188
257
|
schema_builder_t* builder;
|
|
@@ -205,6 +274,32 @@ static VALUE schema_builder_set_nullable(VALUE self, VALUE nullable)
|
|
|
205
274
|
return self;
|
|
206
275
|
}
|
|
207
276
|
|
|
277
|
+
static VALUE schema_builder_set_dictionary_ordered(VALUE self, VALUE dictionary_ordered)
|
|
278
|
+
{
|
|
279
|
+
schema_builder_t* builder;
|
|
280
|
+
GetSchemaBuilder(self, builder);
|
|
281
|
+
|
|
282
|
+
if (RTEST(dictionary_ordered))
|
|
283
|
+
builder->ptr->flags |= ARROW_FLAG_DICTIONARY_ORDERED;
|
|
284
|
+
else
|
|
285
|
+
builder->ptr->flags &= ~ARROW_FLAG_DICTIONARY_ORDERED;
|
|
286
|
+
|
|
287
|
+
return self;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
static VALUE schema_builder_set_map_keys_sorted(VALUE self, VALUE map_keys_sorted)
|
|
291
|
+
{
|
|
292
|
+
schema_builder_t* builder;
|
|
293
|
+
GetSchemaBuilder(self, builder);
|
|
294
|
+
|
|
295
|
+
if (RTEST(map_keys_sorted))
|
|
296
|
+
builder->ptr->flags |= ARROW_FLAG_MAP_KEYS_SORTED;
|
|
297
|
+
else
|
|
298
|
+
builder->ptr->flags &= ~ARROW_FLAG_MAP_KEYS_SORTED;
|
|
299
|
+
|
|
300
|
+
return self;
|
|
301
|
+
}
|
|
302
|
+
|
|
208
303
|
static VALUE schema_builder_validate(VALUE self)
|
|
209
304
|
{
|
|
210
305
|
schema_builder_t* builder;
|
|
@@ -244,8 +339,13 @@ void Init_schema_builder(void)
|
|
|
244
339
|
rb_define_method(cCSchemaBuilder, "set_type_date_time", schema_builder_set_type_date_time, 3);
|
|
245
340
|
rb_define_method(cCSchemaBuilder, "set_format", schema_builder_set_format, 1);
|
|
246
341
|
rb_define_method(cCSchemaBuilder, "set_name", schema_builder_set_name, 1);
|
|
342
|
+
rb_define_method(cCSchemaBuilder, "allocate_children", schema_builder_allocate_children, 1);
|
|
343
|
+
rb_define_method(cCSchemaBuilder, "set_child", schema_builder_set_child, 3);
|
|
344
|
+
rb_define_method(cCSchemaBuilder, "set_dictionary", schema_builder_set_dictionary, 1);
|
|
247
345
|
rb_define_method(cCSchemaBuilder, "set_flags", schema_builder_set_flags, 1);
|
|
248
346
|
rb_define_method(cCSchemaBuilder, "set_nullable", schema_builder_set_nullable, 1);
|
|
347
|
+
rb_define_method(cCSchemaBuilder, "set_dictionary_ordered", schema_builder_set_dictionary_ordered, 1);
|
|
348
|
+
rb_define_method(cCSchemaBuilder, "set_map_keys_sorted", schema_builder_set_map_keys_sorted, 1);
|
|
249
349
|
rb_define_method(cCSchemaBuilder, "validate", schema_builder_validate, 0);
|
|
250
350
|
rb_define_method(cCSchemaBuilder, "finish", schema_builder_finish, 0);
|
|
251
351
|
}
|
|
@@ -87,6 +87,30 @@ module Nanoarrow
|
|
|
87
87
|
@c_builder.append_ints(obj)
|
|
88
88
|
end
|
|
89
89
|
|
|
90
|
+
def append_decimals(obj)
|
|
91
|
+
obj = obj.map { |v| (v.nil? || v.is_a?(BigDecimal)) ? v : BigDecimal(v.to_s) }
|
|
92
|
+
bitwidth = @schema_view.type_id == Type::DECIMAL128 ? 128 : 256
|
|
93
|
+
@c_builder.append_decimals(obj, bitwidth, @schema_view.decimal_precision, @schema_view.decimal_scale)
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def append_struct(obj)
|
|
97
|
+
keys = @schema.children.map(&:name)
|
|
98
|
+
objs = keys.map { |k| obj.map { |v| v.nil? ? v : v.fetch(k) } }
|
|
99
|
+
|
|
100
|
+
# check for extra keys
|
|
101
|
+
obj.each do |v|
|
|
102
|
+
if !v.nil? && v.except(*keys).any?
|
|
103
|
+
raise ArgumentError, "extra keys"
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
arrays = @schema.children.zip(objs).map { |s, v| Utils.c_array(v, s) }
|
|
108
|
+
arrays.each_with_index do |a, i|
|
|
109
|
+
@c_builder.set_child(i, a)
|
|
110
|
+
end
|
|
111
|
+
@c_builder.set_length(objs[0].length)
|
|
112
|
+
end
|
|
113
|
+
|
|
90
114
|
ARRAY_BUILDER_FROM_ITERABLE_METHOD = {
|
|
91
115
|
Type::BOOL => :append_bools,
|
|
92
116
|
Type::INT8 => :append_ints,
|
|
@@ -109,7 +133,10 @@ module Nanoarrow
|
|
|
109
133
|
Type::FIXED_SIZE_BINARY => :append_bytes,
|
|
110
134
|
Type::DATE32 => :append_dates,
|
|
111
135
|
Type::DATE64 => :append_dates,
|
|
112
|
-
Type::TIMESTAMP => :append_timestamps
|
|
136
|
+
Type::TIMESTAMP => :append_timestamps,
|
|
137
|
+
Type::DECIMAL128 => :append_decimals,
|
|
138
|
+
Type::DECIMAL256 => :append_decimals,
|
|
139
|
+
Type::STRUCT => :append_struct
|
|
113
140
|
}
|
|
114
141
|
end
|
|
115
142
|
end
|
data/lib/nanoarrow/iterator.rb
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
module Nanoarrow
|
|
2
2
|
class ArrayViewBaseIterator
|
|
3
|
-
def initialize(schema)
|
|
3
|
+
def initialize(schema, array_view: nil)
|
|
4
4
|
@schema = Utils.c_schema(schema)
|
|
5
5
|
@schema_view = Utils.c_schema_view(schema)
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
if array_view.nil?
|
|
8
|
+
@array_view = CArrayView.from_schema(@schema)
|
|
9
|
+
else
|
|
10
|
+
@array_view = array_view
|
|
11
|
+
end
|
|
7
12
|
end
|
|
8
13
|
|
|
9
14
|
def set_array(array)
|
|
@@ -23,11 +28,15 @@ module Nanoarrow
|
|
|
23
28
|
end
|
|
24
29
|
end
|
|
25
30
|
|
|
26
|
-
def initialize(schema)
|
|
27
|
-
super(schema)
|
|
31
|
+
def initialize(schema, array_view: nil)
|
|
32
|
+
super(schema, array_view: array_view)
|
|
33
|
+
|
|
34
|
+
@children = @schema.children.zip(@array_view.children).map { |s, v| make_child(s, v) }
|
|
28
35
|
end
|
|
29
36
|
|
|
30
37
|
def each(&block)
|
|
38
|
+
return to_enum(:each) unless block_given?
|
|
39
|
+
|
|
31
40
|
type_id = @schema_view.type_id
|
|
32
41
|
if !ITEMS_ITER_LOOKUP.include?(type_id)
|
|
33
42
|
raise KeyError, "Can't resolve iterator for type #{@schema_view.type.inspect}"
|
|
@@ -39,6 +48,10 @@ module Nanoarrow
|
|
|
39
48
|
|
|
40
49
|
private
|
|
41
50
|
|
|
51
|
+
def make_child(schema, array_view)
|
|
52
|
+
self.class.new(schema, array_view: array_view)
|
|
53
|
+
end
|
|
54
|
+
|
|
42
55
|
def each_bool(&block)
|
|
43
56
|
@array_view.each_bool(&block)
|
|
44
57
|
end
|
|
@@ -85,6 +98,21 @@ module Nanoarrow
|
|
|
85
98
|
@array_view.each_int(&wrap)
|
|
86
99
|
end
|
|
87
100
|
|
|
101
|
+
def each_decimal(&block)
|
|
102
|
+
bitwidth = @schema_view.type_id == Type::DECIMAL128 ? 128 : 256
|
|
103
|
+
wrap = ->(v) { block.call(v.nil? ? v : BigDecimal(v)) }
|
|
104
|
+
@array_view.each_decimal(bitwidth, @schema_view.decimal_precision, @schema_view.decimal_scale, &wrap)
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def each_struct(&block)
|
|
108
|
+
if @children.any?
|
|
109
|
+
keys = @schema.children.map(&:name)
|
|
110
|
+
@children[0].each.zip(*@children[1..]) do |v|
|
|
111
|
+
block.call(v[0].nil? ? nil : keys.zip(v).to_h)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
88
116
|
ITEMS_ITER_LOOKUP = {
|
|
89
117
|
Type::BOOL => :each_bool,
|
|
90
118
|
Type::INT8 => :each_int,
|
|
@@ -108,6 +136,9 @@ module Nanoarrow
|
|
|
108
136
|
Type::DATE32 => :each_date,
|
|
109
137
|
Type::DATE64 => :each_date,
|
|
110
138
|
Type::TIMESTAMP => :each_timestamp,
|
|
139
|
+
Type::DECIMAL128 => :each_decimal,
|
|
140
|
+
Type::DECIMAL256 => :each_decimal,
|
|
141
|
+
Type::STRUCT => :each_struct
|
|
111
142
|
}
|
|
112
143
|
end
|
|
113
144
|
end
|
data/lib/nanoarrow/schema.rb
CHANGED
|
@@ -18,7 +18,7 @@ module Nanoarrow
|
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
if !name.nil? || !nullable.nil? || !metadata.nil? || !fields.nil?
|
|
21
|
-
@c_schema = @c_schema.modify(
|
|
21
|
+
@c_schema = @c_schema.modify(name:, nullable:, metadata:, children: clean_fields(fields))
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
@c_schema_view = CSchemaView.new(@c_schema)
|
|
@@ -81,5 +81,17 @@ module Nanoarrow
|
|
|
81
81
|
def arrow_c_schema
|
|
82
82
|
@c_schema.arrow_c_schema
|
|
83
83
|
end
|
|
84
|
+
|
|
85
|
+
private
|
|
86
|
+
|
|
87
|
+
def clean_fields(fields)
|
|
88
|
+
if fields.nil?
|
|
89
|
+
fields
|
|
90
|
+
elsif fields.is_a?(Hash)
|
|
91
|
+
fields.transform_values { |v| Utils.c_schema(v) }
|
|
92
|
+
else
|
|
93
|
+
fields.map { |v| Utils.c_schema(v) }
|
|
94
|
+
end
|
|
95
|
+
end
|
|
84
96
|
end
|
|
85
97
|
end
|
data/lib/nanoarrow/types.rb
CHANGED
|
@@ -147,11 +147,17 @@ module Nanoarrow
|
|
|
147
147
|
Schema.new(Type::DICTIONARY, index_type:, value_type:, dictionary_ordered:)
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
def self.sparse_union(fields, nullable: true)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
150
|
+
def self.sparse_union(fields, type_codes: nil, nullable: true)
|
|
151
|
+
if type_codes.nil?
|
|
152
|
+
type_codes = fields.size.times.to_a
|
|
153
|
+
end
|
|
154
|
+
Schema.new(Type::SPARSE_UNION, fields:, type_codes:, nullable:)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.dense_union(fields, type_codes: nil, nullable: true)
|
|
158
|
+
if type_codes.nil?
|
|
159
|
+
type_codes = fields.size.times.to_a
|
|
160
|
+
end
|
|
161
|
+
Schema.new(Type::DENSE_UNION, fields:, type_codes:, nullable:)
|
|
156
162
|
end
|
|
157
163
|
end
|
data/lib/nanoarrow/utils.rb
CHANGED
|
@@ -90,25 +90,61 @@ module Nanoarrow
|
|
|
90
90
|
factory.set_type_fixed_size(type, Integer(params.delete(:byte_width)))
|
|
91
91
|
|
|
92
92
|
elsif type == Type::LIST
|
|
93
|
-
|
|
93
|
+
factory.set_format("+l")
|
|
94
|
+
factory.allocate_children(1)
|
|
95
|
+
factory.set_child(0, "item", c_schema(params.delete(:value_type)))
|
|
94
96
|
|
|
95
97
|
elsif type == Type::LARGE_LIST
|
|
96
|
-
|
|
98
|
+
factory.set_format("+L")
|
|
99
|
+
factory.allocate_children(1)
|
|
100
|
+
factory.set_child(0, "item", c_schema(params.delete(:value_type)))
|
|
97
101
|
|
|
98
102
|
elsif type == Type::FIXED_SIZE_LIST
|
|
99
|
-
|
|
103
|
+
fixed_size = Integer(params.delete(:list_size))
|
|
104
|
+
factory.set_format("+w:%d" % fixed_size)
|
|
105
|
+
factory.allocate_children(1)
|
|
106
|
+
factory.set_child(0, "item", c_schema(params.delete(:value_type)))
|
|
100
107
|
|
|
101
108
|
elsif type == Type::MAP
|
|
102
|
-
|
|
109
|
+
key_schema = c_schema(params.delete(:key_type))
|
|
110
|
+
value_schema = c_schema(params.delete(:value_type))
|
|
111
|
+
|
|
112
|
+
entries = CSchemaBuilder.allocate
|
|
113
|
+
entries.set_format("+s")
|
|
114
|
+
entries.set_nullable(false)
|
|
115
|
+
entries.allocate_children(2)
|
|
116
|
+
entries.set_child(0, "key", key_schema.modify(nullable: false))
|
|
117
|
+
entries.set_child(1, "value", value_schema)
|
|
118
|
+
|
|
119
|
+
factory.set_format("+m")
|
|
120
|
+
factory.allocate_children(1)
|
|
121
|
+
factory.set_child(0, "entries", entries.finish)
|
|
122
|
+
factory.set_nullable(false)
|
|
123
|
+
|
|
124
|
+
if params.include?(:keys_sorted)
|
|
125
|
+
factory.set_map_keys_sorted(params.delete(:keys_sorted))
|
|
126
|
+
end
|
|
103
127
|
|
|
104
128
|
elsif type == Type::DICTIONARY
|
|
105
|
-
|
|
129
|
+
index_type = c_schema(params.delete(:index_type))
|
|
130
|
+
factory.set_format(index_type.format)
|
|
131
|
+
|
|
132
|
+
value_type = c_schema(params.delete(:value_type))
|
|
133
|
+
factory.set_dictionary(value_type)
|
|
134
|
+
|
|
135
|
+
if params.delete(:dictionary_ordered)
|
|
136
|
+
factory.set_dictionary_ordered(true)
|
|
137
|
+
end
|
|
106
138
|
|
|
107
139
|
elsif type == Type::SPARSE_UNION
|
|
108
|
-
|
|
140
|
+
type_codes = params.delete(:type_codes)
|
|
141
|
+
type_codes_str = type_codes.map { |code| Integer(code) }.join(",")
|
|
142
|
+
factory.set_format("+us:#{type_codes_str}")
|
|
109
143
|
|
|
110
144
|
elsif type == Type::DENSE_UNION
|
|
111
|
-
|
|
145
|
+
type_codes = params.delete(:type_codes)
|
|
146
|
+
type_codes_str = type_codes.map { |code| Integer(code) }.join(",")
|
|
147
|
+
factory.set_format("+ud:#{type_codes_str}")
|
|
112
148
|
|
|
113
149
|
else
|
|
114
150
|
factory.set_type(type)
|
data/lib/nanoarrow/version.rb
CHANGED