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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/ext/duckdb/aggregate_function.c +40 -78
- data/ext/duckdb/appender.c +39 -126
- data/ext/duckdb/connection.c +17 -54
- data/ext/duckdb/conveter.c +39 -76
- data/ext/duckdb/function_executor.c +214 -248
- data/ext/duckdb/function_executor.h +10 -0
- data/ext/duckdb/function_vector.c +26 -0
- data/ext/duckdb/function_vector.h +18 -0
- data/ext/duckdb/logical_type.c +88 -170
- data/ext/duckdb/prepared_statement.c +37 -138
- data/ext/duckdb/result.c +15 -84
- data/ext/duckdb/scalar_function.c +9 -69
- data/ext/duckdb/table_function.c +33 -82
- data/ext/duckdb/util.c +53 -2
- data/lib/duckdb/interval.rb +2 -28
- data/lib/duckdb/prepared_statement.rb +5 -0
- data/lib/duckdb/scalar_function_set.rb +1 -2
- data/lib/duckdb/version.rb +1 -1
- metadata +1 -1
|
@@ -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
|
data/ext/duckdb/logical_type.c
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
477
|
-
|
|
478
|
-
|
|
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
|
-
|
|
489
|
-
|
|
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 =
|
|
444
|
+
new_type = create_fn(member_types, member_names, member_size);
|
|
503
445
|
|
|
504
|
-
|
|
505
|
-
|
|
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
|
|
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
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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");
|