duckdb 2.0.0.0 → 2.0.0.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.
@@ -24,4 +24,22 @@ void rbduckdb_vector_set_value_at(duckdb_vector vector,
24
24
  idx_t index,
25
25
  VALUE value);
26
26
 
27
+ /*
28
+ * Load the vector and logical type of each of the `n` columns of `input`.
29
+ * Allocates both arrays with ALLOC_N; release them with
30
+ * rbduckdb_input_columns_free.
31
+ */
32
+ void rbduckdb_input_columns_load(duckdb_data_chunk input,
33
+ idx_t n,
34
+ duckdb_vector **vectors,
35
+ duckdb_logical_type **types);
36
+
37
+ /*
38
+ * Destroy the `n` logical types and free both arrays. NULL arrays are
39
+ * tolerated so it is safe to call when the load never happened.
40
+ */
41
+ void rbduckdb_input_columns_free(duckdb_vector *vectors,
42
+ duckdb_logical_type *types,
43
+ idx_t n);
44
+
27
45
  #endif
@@ -59,6 +59,42 @@ static VALUE allocate(VALUE klass) {
59
59
  return TypedData_Wrap_Struct(klass, &logical_type_data_type, ctx);
60
60
  }
61
61
 
62
+ static duckdb_logical_type logical_type_of(VALUE self) {
63
+ rubyDuckDBLogicalType *ctx;
64
+ TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
65
+ return ctx->logical_type;
66
+ }
67
+
68
+ static VALUE string_at(VALUE self, VALUE vidx, char *(*getter)(duckdb_logical_type, idx_t), const char *error_format, int utf8) {
69
+ VALUE str;
70
+ const char *cstr;
71
+ idx_t idx = NUM2ULL(vidx);
72
+
73
+ cstr = getter(logical_type_of(self), idx);
74
+ if (cstr == NULL) {
75
+ rb_raise(eDuckDBError, error_format, (unsigned long long)idx);
76
+ }
77
+ str = utf8 ? rb_utf8_str_new_cstr(cstr) : rb_str_new_cstr(cstr);
78
+ duckdb_free((void *)cstr);
79
+ return str;
80
+ }
81
+
82
+ static VALUE logical_type_at(VALUE self, VALUE vidx, duckdb_logical_type (*getter)(duckdb_logical_type, idx_t), const char *error_format) {
83
+ duckdb_logical_type found;
84
+ idx_t idx = NUM2ULL(vidx);
85
+
86
+ found = getter(logical_type_of(self), idx);
87
+ if (found == NULL) {
88
+ rb_raise(eDuckDBError, error_format, (unsigned long long)idx);
89
+ }
90
+
91
+ return rbduckdb_create_logical_type(found);
92
+ }
93
+
94
+ static VALUE wrapped_logical_type(VALUE self, duckdb_logical_type (*getter)(duckdb_logical_type)) {
95
+ return rbduckdb_create_logical_type(getter(logical_type_of(self)));
96
+ }
97
+
62
98
  static size_t memsize(const void *p) {
63
99
  return sizeof(rubyDuckDBLogicalType);
64
100
  }
@@ -90,9 +126,7 @@ static VALUE logical_type_initialize(VALUE self, VALUE type_id_arg) {
90
126
 
91
127
  /* :nodoc: */
92
128
  static VALUE logical_type__type(VALUE self) {
93
- rubyDuckDBLogicalType *ctx;
94
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
95
- return INT2FIX(duckdb_get_type_id(ctx->logical_type));
129
+ return INT2FIX(duckdb_get_type_id(logical_type_of(self)));
96
130
  }
97
131
 
98
132
  /*
@@ -103,9 +137,7 @@ static VALUE logical_type__type(VALUE self) {
103
137
  *
104
138
  */
105
139
  static VALUE logical_type_width(VALUE self) {
106
- rubyDuckDBLogicalType *ctx;
107
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
108
- return INT2FIX(duckdb_decimal_width(ctx->logical_type));
140
+ return INT2FIX(duckdb_decimal_width(logical_type_of(self)));
109
141
  }
110
142
 
111
143
  /*
@@ -116,9 +148,7 @@ static VALUE logical_type_width(VALUE self) {
116
148
  *
117
149
  */
118
150
  static VALUE logical_type_scale(VALUE self) {
119
- rubyDuckDBLogicalType *ctx;
120
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
121
- return INT2FIX(duckdb_decimal_scale(ctx->logical_type));
151
+ return INT2FIX(duckdb_decimal_scale(logical_type_of(self)));
122
152
  }
123
153
 
124
154
  /*
@@ -129,9 +159,7 @@ static VALUE logical_type_scale(VALUE self) {
129
159
  *
130
160
  */
131
161
  static VALUE logical_type_child_count(VALUE self) {
132
- rubyDuckDBLogicalType *ctx;
133
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
134
- return INT2FIX(duckdb_struct_type_child_count(ctx->logical_type));
162
+ return INT2FIX(duckdb_struct_type_child_count(logical_type_of(self)));
135
163
  }
136
164
 
137
165
  /*
@@ -142,20 +170,7 @@ static VALUE logical_type_child_count(VALUE self) {
142
170
  *
143
171
  */
144
172
  static VALUE logical_type_child_name_at(VALUE self, VALUE cidx) {
145
- rubyDuckDBLogicalType *ctx;
146
- VALUE cname;
147
- const char *child_name;
148
- idx_t idx = NUM2ULL(cidx);
149
-
150
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
151
-
152
- child_name = duckdb_struct_type_child_name(ctx->logical_type, idx);
153
- if (child_name == NULL) {
154
- rb_raise(eDuckDBError, "fail to get name of %llu child", (unsigned long long)idx);
155
- }
156
- cname = rb_str_new_cstr(child_name);
157
- duckdb_free((void *)child_name);
158
- return cname;
173
+ return string_at(self, cidx, duckdb_struct_type_child_name, "fail to get name of %llu child", 0);
159
174
  }
160
175
 
161
176
  /*
@@ -166,22 +181,21 @@ static VALUE logical_type_child_name_at(VALUE self, VALUE cidx) {
166
181
  *
167
182
  */
168
183
  static VALUE logical_type_child_type(VALUE self) {
169
- rubyDuckDBLogicalType *ctx;
170
184
  duckdb_type type_id;
171
185
  duckdb_logical_type child_logical_type;
186
+ duckdb_logical_type lt = logical_type_of(self);
172
187
  VALUE logical_type = Qnil;
173
188
 
174
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
175
- type_id = duckdb_get_type_id(ctx->logical_type);
189
+ type_id = duckdb_get_type_id(lt);
176
190
 
177
191
  switch(type_id) {
178
192
  case DUCKDB_TYPE_LIST:
179
193
  case DUCKDB_TYPE_MAP:
180
- child_logical_type = duckdb_list_type_child_type(ctx->logical_type);
194
+ child_logical_type = duckdb_list_type_child_type(lt);
181
195
  logical_type = rbduckdb_create_logical_type(child_logical_type);
182
196
  break;
183
197
  case DUCKDB_TYPE_ARRAY:
184
- child_logical_type = duckdb_array_type_child_type(ctx->logical_type);
198
+ child_logical_type = duckdb_array_type_child_type(lt);
185
199
  logical_type = rbduckdb_create_logical_type(child_logical_type);
186
200
  break;
187
201
  default:
@@ -199,20 +213,7 @@ static VALUE logical_type_child_type(VALUE self) {
199
213
  *
200
214
  */
201
215
  static VALUE logical_type_child_type_at(VALUE self, VALUE cidx) {
202
- rubyDuckDBLogicalType *ctx;
203
- duckdb_logical_type struct_child_type;
204
- idx_t idx = NUM2ULL(cidx);
205
-
206
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
207
-
208
- struct_child_type = duckdb_struct_type_child_type(ctx->logical_type, idx);
209
- if (struct_child_type == NULL) {
210
- rb_raise(eDuckDBError,
211
- "Failed to get the struct child type at index %llu",
212
- (unsigned long long)idx);
213
- }
214
-
215
- return rbduckdb_create_logical_type(struct_child_type);
216
+ return logical_type_at(self, cidx, duckdb_struct_type_child_type, "Failed to get the struct child type at index %llu");
216
217
  }
217
218
 
218
219
  /*
@@ -223,9 +224,7 @@ static VALUE logical_type_child_type_at(VALUE self, VALUE cidx) {
223
224
  *
224
225
  */
225
226
  static VALUE logical_type_size(VALUE self) {
226
- rubyDuckDBLogicalType *ctx;
227
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
228
- return INT2FIX(duckdb_array_type_array_size(ctx->logical_type));
227
+ return INT2FIX(duckdb_array_type_array_size(logical_type_of(self)));
229
228
  }
230
229
 
231
230
  /*
@@ -236,14 +235,7 @@ static VALUE logical_type_size(VALUE self) {
236
235
  *
237
236
  */
238
237
  static VALUE logical_type_key_type(VALUE self) {
239
- rubyDuckDBLogicalType *ctx;
240
- duckdb_logical_type key_logical_type;
241
- VALUE logical_type = Qnil;
242
-
243
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
244
- key_logical_type = duckdb_map_type_key_type(ctx->logical_type);
245
- logical_type = rbduckdb_create_logical_type(key_logical_type);
246
- return logical_type;
238
+ return wrapped_logical_type(self, duckdb_map_type_key_type);
247
239
  }
248
240
 
249
241
  /*
@@ -254,14 +246,7 @@ static VALUE logical_type_key_type(VALUE self) {
254
246
  *
255
247
  */
256
248
  static VALUE logical_type_value_type(VALUE self) {
257
- rubyDuckDBLogicalType *ctx;
258
- duckdb_logical_type value_logical_type;
259
- VALUE logical_type = Qnil;
260
-
261
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
262
- value_logical_type = duckdb_map_type_value_type(ctx->logical_type);
263
- logical_type = rbduckdb_create_logical_type(value_logical_type);
264
- return logical_type;
249
+ return wrapped_logical_type(self, duckdb_map_type_value_type);
265
250
  }
266
251
 
267
252
  /*
@@ -272,9 +257,7 @@ static VALUE logical_type_value_type(VALUE self) {
272
257
  *
273
258
  */
274
259
  static VALUE logical_type_member_count(VALUE self) {
275
- rubyDuckDBLogicalType *ctx;
276
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
277
- return INT2FIX(duckdb_union_type_member_count(ctx->logical_type));
260
+ return INT2FIX(duckdb_union_type_member_count(logical_type_of(self)));
278
261
  }
279
262
 
280
263
  /*
@@ -285,20 +268,7 @@ static VALUE logical_type_member_count(VALUE self) {
285
268
  *
286
269
  */
287
270
  static VALUE logical_type_member_name_at(VALUE self, VALUE midx) {
288
- rubyDuckDBLogicalType *ctx;
289
- VALUE mname;
290
- const char *member_name;
291
- idx_t idx = NUM2ULL(midx);
292
-
293
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
294
-
295
- member_name = duckdb_union_type_member_name(ctx->logical_type, idx);
296
- if (member_name == NULL) {
297
- rb_raise(eDuckDBError, "fail to get name of %llu member", (unsigned long long)idx);
298
- }
299
- mname = rb_str_new_cstr(member_name);
300
- duckdb_free((void *)member_name);
301
- return mname;
271
+ return string_at(self, midx, duckdb_union_type_member_name, "fail to get name of %llu member", 0);
302
272
  }
303
273
 
304
274
  /*
@@ -310,20 +280,7 @@ static VALUE logical_type_member_name_at(VALUE self, VALUE midx) {
310
280
  *
311
281
  */
312
282
  static VALUE logical_type_member_type_at(VALUE self, VALUE midx) {
313
- rubyDuckDBLogicalType *ctx;
314
- duckdb_logical_type union_member_type;
315
- idx_t idx = NUM2ULL(midx);
316
-
317
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
318
-
319
- union_member_type = duckdb_union_type_member_type(ctx->logical_type, idx);
320
- if (union_member_type == NULL) {
321
- rb_raise(eDuckDBError,
322
- "Failed to get the union member type at index %llu",
323
- (unsigned long long)idx);
324
- }
325
-
326
- return rbduckdb_create_logical_type(union_member_type);
283
+ return logical_type_at(self, midx, duckdb_union_type_member_type, "Failed to get the union member type at index %llu");
327
284
  }
328
285
 
329
286
  /*
@@ -334,19 +291,17 @@ static VALUE logical_type_member_type_at(VALUE self, VALUE midx) {
334
291
  *
335
292
  */
336
293
  static VALUE logical_type__internal_type(VALUE self) {
337
- rubyDuckDBLogicalType *ctx;
338
294
  duckdb_type type_id;
339
295
  duckdb_type internal_type_id;
296
+ duckdb_logical_type lt = logical_type_of(self);
340
297
 
341
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
342
-
343
- type_id = duckdb_get_type_id(ctx->logical_type);
298
+ type_id = duckdb_get_type_id(lt);
344
299
  switch (type_id) {
345
300
  case DUCKDB_TYPE_DECIMAL:
346
- internal_type_id = duckdb_decimal_internal_type(ctx->logical_type);
301
+ internal_type_id = duckdb_decimal_internal_type(lt);
347
302
  break;
348
303
  case DUCKDB_TYPE_ENUM:
349
- internal_type_id = duckdb_enum_internal_type(ctx->logical_type);
304
+ internal_type_id = duckdb_enum_internal_type(lt);
350
305
  break;
351
306
  default:
352
307
  internal_type_id = DUCKDB_TYPE_INVALID;
@@ -363,9 +318,7 @@ static VALUE logical_type__internal_type(VALUE self) {
363
318
  *
364
319
  */
365
320
  static VALUE logical_type_dictionary_size(VALUE self) {
366
- rubyDuckDBLogicalType *ctx;
367
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
368
- return INT2FIX(duckdb_enum_dictionary_size(ctx->logical_type));
321
+ return INT2FIX(duckdb_enum_dictionary_size(logical_type_of(self)));
369
322
  }
370
323
 
371
324
  /*
@@ -376,20 +329,7 @@ static VALUE logical_type_dictionary_size(VALUE self) {
376
329
  *
377
330
  */
378
331
  static VALUE logical_type_dictionary_value_at(VALUE self, VALUE didx) {
379
- rubyDuckDBLogicalType *ctx;
380
- VALUE dvalue;
381
- const char *dict_value;
382
- idx_t idx = NUM2ULL(didx);
383
-
384
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
385
-
386
- dict_value = duckdb_enum_dictionary_value(ctx->logical_type, idx);
387
- if (dict_value == NULL) {
388
- rb_raise(eDuckDBError, "fail to get dictionary value of %llu", (unsigned long long)idx);
389
- }
390
- dvalue = rb_utf8_str_new_cstr(dict_value);
391
- duckdb_free((void *)dict_value);
392
- return dvalue;
332
+ return string_at(self, didx, duckdb_enum_dictionary_value, "fail to get dictionary value of %llu", 1);
393
333
  }
394
334
 
395
335
  /*
@@ -400,13 +340,10 @@ static VALUE logical_type_dictionary_value_at(VALUE self, VALUE didx) {
400
340
  *
401
341
  */
402
342
  static VALUE logical_type_get_alias(VALUE self) {
403
- rubyDuckDBLogicalType *ctx;
404
343
  VALUE alias = Qnil;
405
344
  const char *_alias;
406
345
 
407
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
408
-
409
- _alias = duckdb_logical_type_get_alias(ctx->logical_type);
346
+ _alias = duckdb_logical_type_get_alias(logical_type_of(self));
410
347
  if (_alias != NULL) {
411
348
  alias = rb_utf8_str_new_cstr(_alias);
412
349
  }
@@ -422,12 +359,10 @@ static VALUE logical_type_get_alias(VALUE self) {
422
359
  *
423
360
  */
424
361
  static VALUE logical_type_set_alias(VALUE self, VALUE aname) {
425
- rubyDuckDBLogicalType *ctx;
426
362
  VALUE alias = Qnil;
427
363
  const char *_alias = StringValuePtr(aname);
428
364
 
429
- TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
430
- duckdb_logical_type_set_alias(ctx->logical_type, _alias);
365
+ duckdb_logical_type_set_alias(logical_type_of(self), _alias);
431
366
  if (_alias != NULL) {
432
367
  alias = rb_utf8_str_new_cstr(_alias);
433
368
  }
@@ -473,20 +408,27 @@ static VALUE logical_type_s__create_map_type(VALUE klass, VALUE key, VALUE value
473
408
  return rbduckdb_create_logical_type(new_type);
474
409
  }
475
410
 
476
- /* :nodoc: */
477
- static VALUE logical_type_s__create_union_type(VALUE klass, VALUE members) {
478
- idx_t member_size = RHASH_SIZE(members);
411
+ typedef duckdb_logical_type (*create_members_type_fn)(duckdb_logical_type *types, const char **names, idx_t count);
412
+
413
+ static VALUE create_members_type(VALUE members, create_members_type_fn create_fn, const char *type_name) {
414
+ idx_t member_size;
479
415
  duckdb_logical_type *member_types = NULL;
480
416
  const char **member_names = NULL;
481
417
  duckdb_logical_type new_type;
418
+ VALUE types_buf;
419
+ VALUE names_buf;
482
420
  VALUE keys;
483
421
 
422
+ Check_Type(members, T_HASH);
423
+ member_size = RHASH_SIZE(members);
424
+
484
425
  if (member_size == 0) {
485
426
  rb_raise(rb_eArgError, "members hash must not be empty");
486
427
  }
487
428
 
488
- member_types = (duckdb_logical_type *)xcalloc(member_size, sizeof(duckdb_logical_type));
489
- member_names = (const char **)xcalloc(member_size, sizeof(const char *));
429
+ /* GC-managed buffers are released even if reading a member raises. */
430
+ member_types = ALLOCV_N(duckdb_logical_type, types_buf, member_size);
431
+ member_names = ALLOCV_N(const char *, names_buf, member_size);
490
432
 
491
433
  keys = rb_funcall(members, rb_intern("keys"), 0);
492
434
 
@@ -499,54 +441,28 @@ static VALUE logical_type_s__create_union_type(VALUE klass, VALUE members) {
499
441
  member_types[i] = type_ctx->logical_type;
500
442
  }
501
443
 
502
- new_type = duckdb_create_union_type(member_types, member_names, member_size);
444
+ new_type = create_fn(member_types, member_names, member_size);
503
445
 
504
- xfree(member_types);
505
- xfree(member_names);
446
+ RB_GC_GUARD(members);
447
+ RB_GC_GUARD(keys);
448
+ ALLOCV_END(types_buf);
449
+ ALLOCV_END(names_buf);
506
450
 
507
451
  if (!new_type) {
508
- rb_raise(eDuckDBError, "Failed to create union type");
452
+ rb_raise(eDuckDBError, "Failed to create %s type", type_name);
509
453
  }
510
454
 
511
455
  return rbduckdb_create_logical_type(new_type);
512
456
  }
513
457
 
514
458
  /* :nodoc: */
515
- static VALUE logical_type_s__create_struct_type(VALUE klass, VALUE members) {
516
- idx_t member_size = RHASH_SIZE(members);
517
- duckdb_logical_type *member_types = NULL;
518
- const char **member_names = NULL;
519
- duckdb_logical_type new_type;
520
- VALUE keys;
521
-
522
- if (member_size == 0) {
523
- rb_raise(rb_eArgError, "members hash must not be empty");
524
- }
525
-
526
- member_types = (duckdb_logical_type *)xcalloc(member_size, sizeof(duckdb_logical_type));
527
- member_names = (const char **)xcalloc(member_size, sizeof(const char *));
528
-
529
- keys = rb_funcall(members, rb_intern("keys"), 0);
530
-
531
- for (idx_t i = 0; i < member_size; i++) {
532
- VALUE key = rb_ary_entry(keys, (long)i);
533
- VALUE val = rb_hash_aref(members, key);
534
- rubyDuckDBLogicalType *type_ctx = rbduckdb_get_struct_logical_type(val);
535
-
536
- member_names[i] = rb_id2name(SYM2ID(key));
537
- member_types[i] = type_ctx->logical_type;
538
- }
539
-
540
- new_type = duckdb_create_struct_type(member_types, member_names, member_size);
541
-
542
- xfree(member_types);
543
- xfree(member_names);
544
-
545
- if (!new_type) {
546
- rb_raise(eDuckDBError, "Failed to create struct type");
547
- }
459
+ static VALUE logical_type_s__create_union_type(VALUE klass, VALUE members) {
460
+ return create_members_type(members, duckdb_create_union_type, "union");
461
+ }
548
462
 
549
- return rbduckdb_create_logical_type(new_type);
463
+ /* :nodoc: */
464
+ static VALUE logical_type_s__create_struct_type(VALUE klass, VALUE members) {
465
+ return create_members_type(members, duckdb_create_struct_type, "struct");
550
466
  }
551
467
 
552
468
  /* :nodoc: */
@@ -554,12 +470,13 @@ static VALUE logical_type_s__create_enum_type(VALUE klass, VALUE members) {
554
470
  idx_t member_size = RARRAY_LEN(members);
555
471
  const char **member_names = NULL;
556
472
  duckdb_logical_type new_type;
473
+ VALUE names_buf;
557
474
 
558
475
  if (member_size == 0) {
559
476
  rb_raise(rb_eArgError, "members must not be empty");
560
477
  }
561
478
 
562
- member_names = (const char **)xcalloc(member_size, sizeof(const char *));
479
+ member_names = ALLOCV_N(const char *, names_buf, member_size);
563
480
 
564
481
  for (idx_t i = 0; i < member_size; i++) {
565
482
  VALUE val = rb_ary_entry(members, (long)i);
@@ -568,7 +485,8 @@ static VALUE logical_type_s__create_enum_type(VALUE klass, VALUE members) {
568
485
 
569
486
  new_type = duckdb_create_enum_type(member_names, member_size);
570
487
 
571
- xfree(member_names);
488
+ RB_GC_GUARD(members);
489
+ ALLOCV_END(names_buf);
572
490
 
573
491
  if (!new_type) {
574
492
  rb_raise(eDuckDBError, "Failed to create enum type");