duckdb 1.2.1.0 → 1.3.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d8003b16f724b8a5c4863dbc507476601992e002767aa3cf7cfd7d87583265bc
4
- data.tar.gz: a82ef0f5617349c568dd2be3cb8ad1deb5bdee8796483e376eaabc266232f280
3
+ metadata.gz: 419a694a8223198ebddb3470cddc96c164fa684ebde604edf5d0df401376c0d5
4
+ data.tar.gz: c832f287dc1fa48532d2b69dc49c0de13f5d9f2811a49cf3dcd5ba23f985be71
5
5
  SHA512:
6
- metadata.gz: 8220ad5939d4c60819636488a783118ba8040429348ad157515ea1801fe9462ad20e2fff12440ce3e1ffae642f3d6fca0a02b43b4ed8958a105cfd079f85de47
7
- data.tar.gz: f221a85106b80b654750faeb855c51ff760d82082cb86d7c77834c20194ab71b21feff55d883f1d2d13b1dac699bb50ff6fc5473a04db0e50f4dbbfcb1cd5d22
6
+ metadata.gz: e48b21a62da9e1dff74bc2b2ecc775e93c1fbd01691bed443fd04686875e6b5285a4f4d61ea7befb961bbc2c98c610caa0da712fdbd339b3b5efe83d07c4bfc3
7
+ data.tar.gz: 06f7a29029833de5f912343432c8391cecb3404c0069b14d190617291634f790ea55433f5178d9114bd6f7e4a2c7729ce9b808343c48d820842f96fa771bbe22
@@ -15,8 +15,8 @@ jobs:
15
15
  runs-on: macos-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.1.6', '3.2.7', '3.3.7', '3.4.2', 'head']
19
- duckdb: ['1.2.1', '1.1.3', '1.1.1']
18
+ ruby: ['3.2.7', '3.3.8', '3.4.2', 'head', '3.5.0-preview1']
19
+ duckdb: ['1.2.2', '1.1.3', '1.1.1', '1.3.0']
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v4
@@ -15,8 +15,8 @@ jobs:
15
15
  runs-on: ubuntu-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.1.6', '3.2.7', '3.3.7', '3.4.2', 'head']
19
- duckdb: ['1.2.1', '1.1.3', '1.1.1']
18
+ ruby: ['3.2.7', '3.3.8', '3.4.2', 'head', '3.5.0-preview1']
19
+ duckdb: ['1.2.2', '1.1.3', '1.1.1', '1.3.0']
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v4
@@ -15,8 +15,9 @@ jobs:
15
15
  runs-on: windows-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.1.6', '3.2.6', '3.3.6', '3.4.1', 'ucrt', 'mingw', 'mswin', 'head']
19
- duckdb: ['1.2.1', '1.1.3', '1.1.1']
18
+ # ruby: ['3.2.6', '3.3.8', '3.4.1', 'ucrt', 'mingw', 'mswin', 'head']
19
+ ruby: ['3.2.6', '3.3.8', '3.4.1', 'ucrt', 'mingw', 'mswin']
20
+ duckdb: ['1.2.2', '1.1.3', '1.1.1', '1.3.0']
20
21
 
21
22
  steps:
22
23
  - uses: actions/checkout@v4
data/CHANGELOG.md CHANGED
@@ -1,8 +1,33 @@
1
1
  # Changelog
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
+
4
5
  # Unreleased
5
6
 
7
+ # 1.3.0.0 - 2025-05-31
8
+ - bump duckdb to 1.3.0 on CI.
9
+
10
+ ## Breaking changes
11
+ - `DuckDB::Result#streaming?` is deprecated.
12
+ - The second argument of `DuckDB::PendingResult.new` is now meaningless. The result is the same when it is set to true.
13
+ - `DuckDB::PreparedStatement#pending_prepared` behaves the same as `DuckDB::PreparedStatement#pending_prepared_stream`.
14
+ - `DuckDB::PreparedStatement#pending_prepared_stream` will be depreacted. Use `pending_prepared` instead.
15
+ - `DuckDB::Connection#async_query` behaves the same as `DuckDB::Connection#async_query_stream`.
16
+ - `DuckDB::Connection#async_query_stream` will be deprecated. Use `async_query` instead.
17
+ - `DuckDB::Result#chunk_each`, `DuckDB::Result.use_chunk_each`, `DuckDB::Result.use_chunk_each?` are deprecated.
18
+
19
+ # 1.2.2.0 - 2025-05-11
20
+ - drop Ruby 3.1.
21
+ - implement `DuckDB::InstanceCache` class.
22
+ - bump duckdb to 1.2.2 on CI.
23
+ - add `DuckDB::PreparedStatement#bind_uint8`, `DuckDB::PreparedStatement#bind_uint16`,
24
+ `DuckDB::PreparedStatement#bind_uint32`, `DuckDB::PreparedStatement#bind_uint64`.
25
+ - add `DuckDB::LogicalType` class.
26
+ - `DuckDB::LogicalType` class is under construction. `DuckDB::LogicalType#internal_type`,
27
+ `DuckDB::LogicalType#dictionary_size`, `DuckDB::LogicalType#dictionary_value_at`,
28
+ `DuckDB::LogicalType#each_dictionary_value`, `DuckDB::LogicalType#alias`, and
29
+ `DuckDB::LogicalType#alias=`are available.
30
+
6
31
  # 1.2.1.0 - 2025-03-30
7
32
  - bump duckdb v1.2.1 on CI.
8
33
  - drop duckdb v1.0.0.
data/Dockerfile CHANGED
@@ -1,11 +1,12 @@
1
- ARG RUBY_VERSION=3.4.2
1
+ ARG RUBY_VERSION=3.4.4
2
2
  FROM ruby:${RUBY_VERSION}
3
3
 
4
- ARG DUCKDB_VERSION=1.2.1
4
+ ARG DUCKDB_VERSION=1.3.0
5
5
  ARG VALGRIND_VERSION=3.21.0
6
6
 
7
- RUN apt update -qq && \
8
- apt install -y build-essential curl git wget libc6-dbg
7
+ RUN apt-get update -qq && \
8
+ apt-get install -y --no-install-recommends build-essential curl git wget libc6-dbg && \
9
+ apt-get clean
9
10
 
10
11
  COPY getduckdb.sh .
11
12
  RUN ./getduckdb.sh
data/Gemfile.lock CHANGED
@@ -1,32 +1,32 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (1.2.1.0)
4
+ duckdb (1.3.0.0)
5
5
  bigdecimal (>= 3.1.4)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  benchmark-ips (2.14.0)
11
- bigdecimal (3.1.9)
12
- mini_portile2 (2.8.8)
11
+ bigdecimal (3.2.0)
12
+ mini_portile2 (2.8.9)
13
13
  minitest (5.25.5)
14
- nokogiri (1.18.6)
14
+ nokogiri (1.18.8)
15
15
  mini_portile2 (~> 2.8.2)
16
16
  racc (~> 1.4)
17
- nokogiri (1.18.6-aarch64-linux-gnu)
17
+ nokogiri (1.18.8-aarch64-linux-gnu)
18
18
  racc (~> 1.4)
19
- nokogiri (1.18.6-arm-linux-gnu)
19
+ nokogiri (1.18.8-arm-linux-gnu)
20
20
  racc (~> 1.4)
21
- nokogiri (1.18.6-arm64-darwin)
21
+ nokogiri (1.18.8-arm64-darwin)
22
22
  racc (~> 1.4)
23
- nokogiri (1.18.6-x86_64-darwin)
23
+ nokogiri (1.18.8-x86_64-darwin)
24
24
  racc (~> 1.4)
25
- nokogiri (1.18.6-x86_64-linux-gnu)
25
+ nokogiri (1.18.8-x86_64-linux-gnu)
26
26
  racc (~> 1.4)
27
27
  racc (1.8.1)
28
- rake (13.2.1)
29
- rake-compiler (1.2.9)
28
+ rake (13.3.0)
29
+ rake-compiler (1.3.0)
30
30
  rake
31
31
  ruby_memcheck (3.0.1)
32
32
  nokogiri
data/README.md CHANGED
@@ -146,7 +146,7 @@ result = con.prepare('SELECT * FROM users WHERE name = $name AND email = $email'
146
146
  You can use async query.
147
147
 
148
148
  ```ruby
149
- pending_result = con.async_query_stream('SLOW QUERY')
149
+ pending_result = con.async_query('SLOW QUERY')
150
150
  pending_result.execute_task while pending_result.state == :not_ready
151
151
 
152
152
  result = pending_result.execute_pending
@@ -118,6 +118,14 @@ static VALUE duckdb_database_close(VALUE self) {
118
118
  return self;
119
119
  }
120
120
 
121
+ VALUE rbduckdb_create_database_obj(duckdb_database db) {
122
+ VALUE obj = allocate(cDuckDBDatabase);
123
+ rubyDuckDB *ctx;
124
+ TypedData_Get_Struct(obj, rubyDuckDB, &database_data_type, ctx);
125
+ ctx->db = db;
126
+ return obj;
127
+ }
128
+
121
129
  void rbduckdb_init_duckdb_database(void) {
122
130
  #if 0
123
131
  VALUE mDuckDB = rb_define_module("DuckDB");
@@ -8,6 +8,7 @@ struct _rubyDuckDB {
8
8
  typedef struct _rubyDuckDB rubyDuckDB;
9
9
 
10
10
  rubyDuckDB *rbduckdb_get_struct_database(VALUE obj);
11
+ VALUE rbduckdb_create_database_obj(duckdb_database db);
11
12
  void rbduckdb_init_duckdb_database(void);
12
13
 
13
14
  #endif
data/ext/duckdb/duckdb.c CHANGED
@@ -39,4 +39,7 @@ Init_duckdb_native(void) {
39
39
  rbduckdb_init_duckdb_config();
40
40
  rbduckdb_init_duckdb_converter();
41
41
  rbduckdb_init_duckdb_extracted_statements();
42
+ #ifdef HAVE_DUCKDB_H_GE_V1_2_0
43
+ rbduckdb_init_duckdb_instance_cache();
44
+ #endif
42
45
  }
@@ -64,6 +64,9 @@ have_func('duckdb_result_error_type', 'duckdb.h')
64
64
  # check duckdb >= 1.2.0
65
65
  have_func('duckdb_create_instance_cache', 'duckdb.h')
66
66
 
67
+ # check duckdb >= 1.3.0
68
+ have_func('duckdb_get_table_names', 'duckdb.h')
69
+
67
70
  # Building with enabled DUCKDB_API_NO_DEPRECATED is failed with DuckDB v1.1.0 only.
68
71
  # DuckDB v1.1.1 is fixed this issue https://github.com/duckdb/duckdb/issues/13872.
69
72
  have_const('DUCKDB_TYPE_SQLNULL', 'duckdb.h')
@@ -0,0 +1,108 @@
1
+ #include "ruby-duckdb.h"
2
+
3
+ #ifdef HAVE_DUCKDB_H_GE_V1_2_0
4
+ VALUE cDuckDBInstanceCache;
5
+
6
+ static void deallocate(void * ctx);
7
+ static VALUE allocate(VALUE klass);
8
+ static size_t memsize(const void *p);
9
+ static VALUE duckdb_instance_cache_initialize(VALUE self);
10
+ static VALUE duckdb_instance_cache_get_or_create(int argc, VALUE *argv, VALUE self);
11
+ static VALUE duckdb_instance_cache_destroy(VALUE self);
12
+
13
+ static const rb_data_type_t instance_cache_data_type = {
14
+ "DuckDB/InstanceCache",
15
+ {NULL, deallocate, memsize,},
16
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
17
+ };
18
+
19
+ static void deallocate(void * ctx) {
20
+ rubyDuckDBInstanceCache *p = (rubyDuckDBInstanceCache *)ctx;
21
+
22
+ if (p->instance_cache) {
23
+ duckdb_destroy_instance_cache(&(p->instance_cache));
24
+ }
25
+ xfree(p);
26
+ }
27
+
28
+ static size_t memsize(const void *p) {
29
+ return sizeof(rubyDuckDBInstanceCache);
30
+ }
31
+
32
+ static VALUE allocate(VALUE klass) {
33
+ rubyDuckDBInstanceCache *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBInstanceCache));
34
+ return TypedData_Wrap_Struct(klass, &instance_cache_data_type, ctx);
35
+ }
36
+
37
+ static VALUE duckdb_instance_cache_initialize(VALUE self) {
38
+ rubyDuckDBInstanceCache *ctx;
39
+
40
+ TypedData_Get_Struct(self, rubyDuckDBInstanceCache, &instance_cache_data_type, ctx);
41
+
42
+ ctx->instance_cache = duckdb_create_instance_cache();
43
+ if (ctx->instance_cache == NULL) {
44
+ rb_raise(eDuckDBError, "Failed to create instance cache");
45
+ }
46
+
47
+ return self;
48
+ }
49
+
50
+ /* :nodoc: */
51
+ static VALUE duckdb_instance_cache_get_or_create(int argc, VALUE *argv, VALUE self) {
52
+ VALUE vpath = Qnil;
53
+ VALUE vconfig = Qnil;
54
+ const char *path = NULL;
55
+ char *error = NULL;
56
+ duckdb_config config = NULL;
57
+ duckdb_database db;
58
+ rubyDuckDBInstanceCache *ctx;
59
+
60
+ rb_scan_args(argc, argv, "02", &vpath, &vconfig);
61
+ if (!NIL_P(vpath)) {
62
+ path = StringValuePtr(vpath);
63
+ }
64
+ if (!NIL_P(vconfig)) {
65
+ if (!rb_obj_is_kind_of(vconfig, cDuckDBConfig)) {
66
+ rb_raise(rb_eTypeError, "The second argument must be DuckDB::Config object.");
67
+ }
68
+ rubyDuckDBConfig *ctx_config = get_struct_config(vconfig);
69
+ config = ctx_config->config;
70
+ }
71
+
72
+ TypedData_Get_Struct(self, rubyDuckDBInstanceCache, &instance_cache_data_type, ctx);
73
+
74
+ if (duckdb_get_or_create_from_cache(ctx->instance_cache, path, &db, config, &error) == DuckDBError) {
75
+ if (error) {
76
+ VALUE message = rb_str_new_cstr(error);
77
+ duckdb_free(error);
78
+ rb_raise(eDuckDBError, "%s", StringValuePtr(message));
79
+ } else {
80
+ rb_raise(eDuckDBError, "Failed to get or create database from instance cache");
81
+ }
82
+ }
83
+ return rbduckdb_create_database_obj(db);
84
+ }
85
+
86
+ static VALUE duckdb_instance_cache_destroy(VALUE self) {
87
+ rubyDuckDBInstanceCache *ctx;
88
+ TypedData_Get_Struct(self, rubyDuckDBInstanceCache, &instance_cache_data_type, ctx);
89
+
90
+ if (ctx->instance_cache) {
91
+ duckdb_destroy_instance_cache(&(ctx->instance_cache));
92
+ ctx->instance_cache = NULL;
93
+ }
94
+
95
+ return Qnil;
96
+ }
97
+
98
+ void rbduckdb_init_duckdb_instance_cache(void) {
99
+ #if 0
100
+ VALUE mDuckDB = rb_define_module("DuckDB");
101
+ #endif
102
+ cDuckDBInstanceCache = rb_define_class_under(mDuckDB, "InstanceCache", rb_cObject);
103
+ rb_define_method(cDuckDBInstanceCache, "initialize", duckdb_instance_cache_initialize, 0);
104
+ rb_define_method(cDuckDBInstanceCache, "get_or_create", duckdb_instance_cache_get_or_create, -1);
105
+ rb_define_method(cDuckDBInstanceCache, "destroy", duckdb_instance_cache_destroy, 0);
106
+ rb_define_alloc_func(cDuckDBInstanceCache, allocate);
107
+ }
108
+ #endif
@@ -0,0 +1,17 @@
1
+ #ifndef RUBY_DUCKDB_INSTANCE_CACHE_H
2
+ #define RUBY_DUCKDB_INSTANCE_CACHE_H
3
+
4
+ #ifdef HAVE_DUCKDB_H_GE_V1_2_0
5
+
6
+ struct _rubyDuckDBInstanceCache {
7
+ duckdb_instance_cache instance_cache;
8
+ };
9
+
10
+ typedef struct _rubyDuckDBInstanceCache rubyDuckDBInstanceCache;
11
+
12
+ void rbduckdb_init_duckdb_instance_cache(void);
13
+
14
+ #endif
15
+
16
+ #endif
17
+
@@ -18,6 +18,11 @@ static VALUE duckdb_logical_type_value_type(VALUE self);
18
18
  static VALUE duckdb_logical_type_member_count(VALUE self);
19
19
  static VALUE duckdb_logical_type_member_name_at(VALUE self, VALUE midx);
20
20
  static VALUE duckdb_logical_type_member_type_at(VALUE self, VALUE midx);
21
+ static VALUE duckdb_logical_type__internal_type(VALUE self);
22
+ static VALUE duckdb_logical_type_dictionary_size(VALUE self);
23
+ static VALUE duckdb_logical_type_dictionary_value_at(VALUE self, VALUE didx);
24
+ static VALUE duckdb_logical_type__get_alias(VALUE self);
25
+ static VALUE duckdb_logical_type__set_alias(VALUE self, VALUE aname);
21
26
 
22
27
  static const rb_data_type_t logical_type_data_type = {
23
28
  "DuckDB/LogicalType",
@@ -288,6 +293,115 @@ static VALUE duckdb_logical_type_member_type_at(VALUE self, VALUE midx) {
288
293
  return rbduckdb_create_logical_type(union_member_type);
289
294
  }
290
295
 
296
+ /*
297
+ * call-seq:
298
+ * enum_col.logical_type.internal_type -> Symbol
299
+ *
300
+ * Returns the logical type's internal type.
301
+ *
302
+ */
303
+ static VALUE duckdb_logical_type__internal_type(VALUE self) {
304
+ rubyDuckDBLogicalType *ctx;
305
+ duckdb_type type_id;
306
+ duckdb_type internal_type_id;
307
+
308
+ TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
309
+
310
+ type_id = duckdb_get_type_id(ctx->logical_type);
311
+ switch (type_id) {
312
+ case DUCKDB_TYPE_DECIMAL:
313
+ internal_type_id = duckdb_decimal_internal_type(ctx->logical_type);
314
+ break;
315
+ case DUCKDB_TYPE_ENUM:
316
+ internal_type_id = duckdb_enum_internal_type(ctx->logical_type);
317
+ break;
318
+ default:
319
+ internal_type_id = DUCKDB_TYPE_INVALID;
320
+ }
321
+
322
+ return INT2FIX(internal_type_id);
323
+ }
324
+
325
+ /*
326
+ * call-seq:
327
+ * enum_col.logical_type.dictionary_size -> Integer
328
+ *
329
+ * Returns the dictionary size of the enum type.
330
+ *
331
+ */
332
+ static VALUE duckdb_logical_type_dictionary_size(VALUE self) {
333
+ rubyDuckDBLogicalType *ctx;
334
+ TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
335
+ return INT2FIX(duckdb_enum_dictionary_size(ctx->logical_type));
336
+ }
337
+
338
+ /*
339
+ * call-seq:
340
+ * enum_col.logical_type.dictionary_value_at(index) -> String
341
+ *
342
+ * Returns the dictionary value at the specified index.
343
+ *
344
+ */
345
+ static VALUE duckdb_logical_type_dictionary_value_at(VALUE self, VALUE didx) {
346
+ rubyDuckDBLogicalType *ctx;
347
+ VALUE dvalue;
348
+ const char *dict_value;
349
+ idx_t idx = NUM2ULL(didx);
350
+
351
+ TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
352
+
353
+ dict_value = duckdb_enum_dictionary_value(ctx->logical_type, idx);
354
+ if (dict_value == NULL) {
355
+ rb_raise(eDuckDBError, "fail to get dictionary value of %llu", (unsigned long long)idx);
356
+ }
357
+ dvalue = rb_utf8_str_new_cstr(dict_value);
358
+ duckdb_free((void *)dict_value);
359
+ return dvalue;
360
+ }
361
+
362
+ /*
363
+ * call-seq:
364
+ * col.logical_type.alias -> String
365
+ *
366
+ * Returns the alias of the logical type.
367
+ *
368
+ */
369
+ static VALUE duckdb_logical_type__get_alias(VALUE self) {
370
+ rubyDuckDBLogicalType *ctx;
371
+ VALUE alias = Qnil;
372
+ const char *_alias;
373
+
374
+ TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
375
+
376
+ _alias = duckdb_logical_type_get_alias(ctx->logical_type);
377
+ if (_alias != NULL) {
378
+ alias = rb_utf8_str_new_cstr(_alias);
379
+ }
380
+ duckdb_free((void *)_alias);
381
+ return alias;
382
+ }
383
+
384
+ /*
385
+ * call-seq:
386
+ * col.logical_type.alias(alias) -> String
387
+ *
388
+ * Return the set alias of the logical type.
389
+ *
390
+ */
391
+ static VALUE duckdb_logical_type__set_alias(VALUE self, VALUE aname) {
392
+ rubyDuckDBLogicalType *ctx;
393
+ VALUE alias = Qnil;
394
+ const char *_alias = StringValuePtr(aname);
395
+
396
+ TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
397
+ duckdb_logical_type_set_alias(ctx->logical_type, _alias);
398
+ if (_alias != NULL) {
399
+ alias = rb_utf8_str_new_cstr(_alias);
400
+ }
401
+
402
+ return alias;
403
+ }
404
+
291
405
  VALUE rbduckdb_create_logical_type(duckdb_logical_type logical_type) {
292
406
  VALUE obj;
293
407
  rubyDuckDBLogicalType *ctx;
@@ -320,4 +434,9 @@ void rbduckdb_init_duckdb_logical_type(void) {
320
434
  rb_define_method(cDuckDBLogicalType, "member_count", duckdb_logical_type_member_count, 0);
321
435
  rb_define_method(cDuckDBLogicalType, "member_name_at", duckdb_logical_type_member_name_at, 1);
322
436
  rb_define_method(cDuckDBLogicalType, "member_type_at", duckdb_logical_type_member_type_at, 1);
437
+ rb_define_method(cDuckDBLogicalType, "_internal_type", duckdb_logical_type__internal_type, 0);
438
+ rb_define_method(cDuckDBLogicalType, "dictionary_size", duckdb_logical_type_dictionary_size, 0);
439
+ rb_define_method(cDuckDBLogicalType, "dictionary_value_at", duckdb_logical_type_dictionary_value_at, 1);
440
+ rb_define_method(cDuckDBLogicalType, "get_alias", duckdb_logical_type__get_alias, 0);
441
+ rb_define_method(cDuckDBLogicalType, "set_alias", duckdb_logical_type__set_alias, 1);
323
442
  }
@@ -40,13 +40,9 @@ static VALUE duckdb_pending_result_initialize(int argc, VALUE *argv, VALUE self)
40
40
  VALUE streaming_p = Qfalse;
41
41
  duckdb_state state;
42
42
 
43
- /*
44
- * FIXME: The 2nd argument is deprecated and will be removed in the future.
45
- * The behavior will be same as streaming.
46
43
  if (argc == 2) {
47
- rb_warn("The 2nd argument is deprecated and will be removed in the future.");
44
+ rb_warn("The second argument of `DuckDB::PendingResult#new` is now meaningless. The result is the same when it is set to true.");
48
45
  }
49
- */
50
46
  rb_scan_args(argc, argv, "11", &oDuckDBPreparedStatement, &streaming_p);
51
47
 
52
48
  if (rb_obj_is_kind_of(oDuckDBPreparedStatement, cDuckDBPreparedStatement) != Qtrue) {
@@ -56,20 +52,7 @@ static VALUE duckdb_pending_result_initialize(int argc, VALUE *argv, VALUE self)
56
52
  rubyDuckDBPendingResult *ctx = get_struct_pending_result(self);
57
53
  rubyDuckDBPreparedStatement *stmt = get_struct_prepared_statement(oDuckDBPreparedStatement);
58
54
 
59
- #ifdef DUCKDB_API_NO_DEPRECATED
60
55
  state = duckdb_pending_prepared(stmt->prepared_statement, &(ctx->pending_result));
61
- #else
62
- /*
63
- * FIXME: streaming_p check will be removed in the future.
64
- *
65
- * state = duckdb_pending_prepared(stmt->prepared_statement, &(ctx->pending_result));
66
- */
67
- if (!NIL_P(streaming_p) && streaming_p == Qtrue) {
68
- state = duckdb_pending_prepared_streaming(stmt->prepared_statement, &(ctx->pending_result));
69
- } else {
70
- state = duckdb_pending_prepared(stmt->prepared_statement, &(ctx->pending_result));
71
- }
72
- #endif
73
56
 
74
57
  if (state == DuckDBError) {
75
58
  rb_raise(eDuckDBError, "%s", duckdb_pending_error(ctx->pending_result));
@@ -27,6 +27,10 @@ static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE b
27
27
  static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx);
28
28
  static VALUE duckdb_prepared_statement__statement_type(VALUE self);
29
29
  static VALUE duckdb_prepared_statement__param_type(VALUE self, VALUE vidx);
30
+ static VALUE duckdb_prepared_statement__bind_uint8(VALUE self, VALUE vidx, VALUE val);
31
+ static VALUE duckdb_prepared_statement__bind_uint16(VALUE self, VALUE vidx, VALUE val);
32
+ static VALUE duckdb_prepared_statement__bind_uint32(VALUE self, VALUE vidx, VALUE val);
33
+ static VALUE duckdb_prepared_statement__bind_uint64(VALUE self, VALUE vidx, VALUE val);
30
34
  static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day);
31
35
  static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros);
32
36
  static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
@@ -244,6 +248,7 @@ static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE v
244
248
  return self;
245
249
  }
246
250
 
251
+
247
252
  static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val) {
248
253
  rubyDuckDBPreparedStatement *ctx;
249
254
  idx_t idx = check_index(vidx);
@@ -359,6 +364,62 @@ static VALUE duckdb_prepared_statement__param_type(VALUE self, VALUE vidx) {
359
364
  return INT2FIX(duckdb_param_type(ctx->prepared_statement, NUM2ULL(vidx)));
360
365
  }
361
366
 
367
+ /* :nodoc: */
368
+ static VALUE duckdb_prepared_statement__bind_uint8(VALUE self, VALUE vidx, VALUE val) {
369
+ rubyDuckDBPreparedStatement *ctx;
370
+ idx_t idx = check_index(vidx);
371
+ uint8_t ui8val = (uint8_t)NUM2UINT(val);
372
+
373
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
374
+
375
+ if (duckdb_bind_uint8(ctx->prepared_statement, idx, ui8val) == DuckDBError) {
376
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
377
+ }
378
+ return self;
379
+ }
380
+
381
+ /* :nodoc: */
382
+ static VALUE duckdb_prepared_statement__bind_uint16(VALUE self, VALUE vidx, VALUE val) {
383
+ rubyDuckDBPreparedStatement *ctx;
384
+ idx_t idx = check_index(vidx);
385
+ uint16_t ui16val = (uint16_t)NUM2UINT(val);
386
+
387
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
388
+
389
+ if (duckdb_bind_uint16(ctx->prepared_statement, idx, ui16val) == DuckDBError) {
390
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
391
+ }
392
+ return self;
393
+ }
394
+
395
+ /* :nodoc: */
396
+ static VALUE duckdb_prepared_statement__bind_uint32(VALUE self, VALUE vidx, VALUE val) {
397
+ rubyDuckDBPreparedStatement *ctx;
398
+ idx_t idx = check_index(vidx);
399
+ uint32_t ui32val = (uint32_t)NUM2UINT(val);
400
+
401
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
402
+
403
+ if (duckdb_bind_uint32(ctx->prepared_statement, idx, ui32val) == DuckDBError) {
404
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
405
+ }
406
+ return self;
407
+ }
408
+
409
+ /* :nodoc: */
410
+ static VALUE duckdb_prepared_statement__bind_uint64(VALUE self, VALUE vidx, VALUE val) {
411
+ rubyDuckDBPreparedStatement *ctx;
412
+ idx_t idx = check_index(vidx);
413
+ uint64_t ui64val = (uint64_t)NUM2ULL(val);
414
+
415
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
416
+
417
+ if (duckdb_bind_uint64(ctx->prepared_statement, idx, ui64val) == DuckDBError) {
418
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
419
+ }
420
+ return self;
421
+ }
422
+
362
423
  /* :nodoc: */
363
424
  static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day) {
364
425
  rubyDuckDBPreparedStatement *ctx;
@@ -511,6 +572,10 @@ void rbduckdb_init_duckdb_prepared_statement(void) {
511
572
  rb_define_method(cDuckDBPreparedStatement, "bind_varchar", duckdb_prepared_statement_bind_varchar, 2);
512
573
  rb_define_method(cDuckDBPreparedStatement, "bind_blob", duckdb_prepared_statement_bind_blob, 2);
513
574
  rb_define_method(cDuckDBPreparedStatement, "bind_null", duckdb_prepared_statement_bind_null, 1);
575
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_uint8", duckdb_prepared_statement__bind_uint8, 2);
576
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_uint16", duckdb_prepared_statement__bind_uint16, 2);
577
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_uint32", duckdb_prepared_statement__bind_uint32, 2);
578
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_uint64", duckdb_prepared_statement__bind_uint64, 2);
514
579
  rb_define_private_method(cDuckDBPreparedStatement, "_statement_type", duckdb_prepared_statement__statement_type, 0);
515
580
  rb_define_private_method(cDuckDBPreparedStatement, "_param_type", duckdb_prepared_statement__param_type, 1);
516
581
  rb_define_private_method(cDuckDBPreparedStatement, "_bind_date", duckdb_prepared_statement__bind_date, 4);
data/ext/duckdb/result.c CHANGED
@@ -26,9 +26,7 @@ static size_t memsize(const void *p);
26
26
  static VALUE duckdb_result_column_count(VALUE oDuckDBResult);
27
27
  static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult);
28
28
  static VALUE duckdb_result_columns(VALUE oDuckDBResult);
29
- static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult);
30
29
  static VALUE destroy_data_chunk(VALUE arg);
31
- static VALUE duckdb_result__chunk_each(VALUE oDuckDBResult);
32
30
 
33
31
  static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult);
34
32
  static VALUE yield_rows(VALUE arg);
@@ -168,63 +166,12 @@ static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
168
166
  return ary;
169
167
  }
170
168
 
171
- /*
172
- * :nodoc:
173
- */
174
- static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult) {
175
- rubyDuckDBResult *ctx;
176
-
177
- #ifdef DUCKDB_API_NO_DEPRECATED
178
- return Qtrue;
179
- #else
180
- rb_warn("`DuckDB::Result#streaming?` will be deprecated in the future.");
181
- /* FIXME streaming is allways true. so this method is not useful and deprecated. */
182
- TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
183
- return duckdb_result_is_streaming(ctx->result) ? Qtrue : Qfalse;
184
- #endif
185
- }
186
-
187
169
  static VALUE destroy_data_chunk(VALUE arg) {
188
170
  struct chunk_arg *p = (struct chunk_arg *)arg;
189
171
  duckdb_destroy_data_chunk(&(p->chunk));
190
172
  return Qnil;
191
173
  }
192
174
 
193
- /* :nodoc: */
194
- static VALUE duckdb_result__chunk_each(VALUE oDuckDBResult) {
195
- /*
196
- #ifdef HAVE_DUCKDB_H_GE_V1_0_0
197
- return duckdb_result__chunk_stream(oDuckDBResult);
198
- #else
199
- */
200
- rubyDuckDBResult *ctx;
201
- struct chunk_arg arg;
202
- idx_t chunk_count;
203
- idx_t chunk_idx;
204
-
205
- #ifdef DUCKDB_API_NO_DEPRECATED
206
- //TODO: use duckdb_fetch_chunk instead of duckdb_result_chunk_count and duckdb_result_get_chunk.
207
- // duckdb_result_chunk_count will be deprecated in the future.
208
- // duckdb_result_get_chunk will be deprecated in the future.
209
- #else
210
- TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
211
-
212
- arg.col_count = duckdb_column_count(&(ctx->result));
213
- chunk_count = duckdb_result_chunk_count(ctx->result);
214
-
215
- RETURN_ENUMERATOR(oDuckDBResult, 0, 0);
216
-
217
- for (chunk_idx = 0; chunk_idx < chunk_count; chunk_idx++) {
218
- arg.chunk = duckdb_result_get_chunk(ctx->result, chunk_idx);
219
- rb_ensure(yield_rows, (VALUE)&arg, destroy_data_chunk, (VALUE)&arg);
220
- }
221
- #endif
222
- return Qnil;
223
- /*
224
- #endif
225
- */
226
- }
227
-
228
175
  /* :nodoc: */
229
176
  static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult) {
230
177
  rubyDuckDBResult *ctx;
@@ -877,8 +824,6 @@ void rbduckdb_init_duckdb_result(void) {
877
824
  rb_define_method(cDuckDBResult, "column_count", duckdb_result_column_count, 0);
878
825
  rb_define_method(cDuckDBResult, "rows_changed", duckdb_result_rows_changed, 0);
879
826
  rb_define_method(cDuckDBResult, "columns", duckdb_result_columns, 0);
880
- rb_define_method(cDuckDBResult, "streaming?", duckdb_result_streaming_p, 0);
881
- rb_define_private_method(cDuckDBResult, "_chunk_each", duckdb_result__chunk_each, 0);
882
827
  rb_define_private_method(cDuckDBResult, "_chunk_stream", duckdb_result__chunk_stream, 0);
883
828
  rb_define_private_method(cDuckDBResult, "_column_type", duckdb_result__column_type, 1);
884
829
  rb_define_private_method(cDuckDBResult, "_return_type", duckdb_result__return_type, 0);
@@ -16,6 +16,10 @@
16
16
  #define HAVE_DUCKDB_H_GE_V1_2_0 1
17
17
  #endif
18
18
 
19
+ #ifdef HAVE_DUCKDB_GET_TABLE_NAMES
20
+ #define HAVE_DUCKDB_H_GE_V1_3_0 1
21
+ #endif
22
+
19
23
  #include "./error.h"
20
24
  #include "./database.h"
21
25
  #include "./connection.h"
@@ -32,6 +36,10 @@
32
36
  #include "./appender.h"
33
37
  #include "./config.h"
34
38
 
39
+ #ifdef HAVE_DUCKDB_H_GE_V1_2_0
40
+ #include "./instance_cache.h"
41
+ #endif
42
+
35
43
  extern VALUE mDuckDB;
36
44
  extern VALUE cDuckDBDatabase;
37
45
  extern VALUE cDuckDBConnection;
@@ -43,4 +51,8 @@ extern VALUE cDuckDBPreparedStatement;
43
51
  extern VALUE PositiveInfinity;
44
52
  extern VALUE NegativeInfinity;
45
53
 
54
+ #ifdef HAVE_DUCKDB_H_GE_V1_2_0
55
+ extern VALUE cDuckDBInstanceCache;
56
+ #endif
57
+
46
58
  #endif
@@ -81,10 +81,9 @@ module DuckDB
81
81
  # result = pending_result.execute_pending
82
82
  # result.each.first
83
83
  def async_query_stream(sql, *args, **kwargs)
84
- prepare(sql) do |stmt|
85
- stmt.bind_args(*args, **kwargs)
86
- stmt.pending_prepared_stream
87
- end
84
+ warn("`#{self.class}#{__method__}` will be deprecated. Use `#{self.class}#async_query` instead.")
85
+
86
+ async_query(sql, *args, **kwargs)
88
87
  end
89
88
 
90
89
  # connects DuckDB database
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ if defined?(DuckDB::InstanceCache)
4
+
5
+ module DuckDB
6
+ # The DuckDB::InstanceCache is necessary if a client/program (re)opens
7
+ # multiple databases to the same file within the same statement.
8
+ #
9
+ # require 'duckdb'
10
+ # cache = DuckDB::InstanceCache.new
11
+ # db1 = cache.get(path: 'db.duckdb')
12
+ # db2 = cache.get(path: 'db.duckdb')
13
+ class InstanceCache
14
+ # :call-seq:
15
+ # instance_cache.get(path:, config:) -> self
16
+ #
17
+ # Returns a DuckDB::Database object for the given path and config.
18
+ # db1 = cache.get(path: 'db.duckdb')
19
+ # db2 = cache.get(path: 'db.duckdb')
20
+ def get(path: nil, config: nil)
21
+ get_or_create(path, config)
22
+ end
23
+ end
24
+ end
25
+
26
+ end
@@ -2,6 +2,9 @@
2
2
 
3
3
  module DuckDB
4
4
  class LogicalType
5
+ alias :alias get_alias
6
+ alias :alias= set_alias
7
+
5
8
  # returns logical type's type symbol
6
9
  # `:unknown` means that the logical type's type is unknown/unsupported by ruby-duckdb.
7
10
  # `:invalid` means that the logical type's type is invalid in duckdb.
@@ -19,6 +22,24 @@ module DuckDB
19
22
  DuckDB::Converter::IntToSym.type_to_sym(type_id)
20
23
  end
21
24
 
25
+ # returns logical type's internal type symbol for Decimal or Enum types
26
+ # `:unknown` means that the logical type's type is unknown/unsupported by ruby-duckdb.
27
+ # `:invalid` means that the logical type's type is invalid in duckdb.
28
+ #
29
+ # require 'duckdb'
30
+ # db = DuckDB::Database.open
31
+ # con = db.connect
32
+ # con.query("CREATE TYPE mood AS ENUM ('happy', 'sad')")
33
+ # con.query("CREATE TABLE emotions (id INTEGER, enum_col mood)")
34
+ #
35
+ # users = con.query('SELECT * FROM emotions')
36
+ # ernum_col = users.columns.find { |col| col.name == 'enum_col' }
37
+ # enum_col.logical_type.internal_type #=> :utinyint
38
+ def internal_type
39
+ type_id = _internal_type
40
+ DuckDB::Converter::IntToSym.type_to_sym(type_id)
41
+ end
42
+
22
43
  # Iterates over each union member name.
23
44
  #
24
45
  # When a block is provided, this method yields each union member name in
@@ -106,5 +127,27 @@ module DuckDB
106
127
  yield child_type_at(i)
107
128
  end
108
129
  end
130
+
131
+ # Iterates over each enum dictionary value.
132
+ #
133
+ # When a block is provided, this method yields each enum dictionary value
134
+ # in order. It also returns the total number of dictionary values yielded.
135
+ #
136
+ # enum_logical_type.each_value do |value|
137
+ # puts "Enum value: #{value}"
138
+ # end
139
+ #
140
+ # If no block is given, an Enumerator is returned, which can be used to
141
+ # retrieve all enum dictionary values.
142
+ #
143
+ # values = enum_logical_type.each_value.to_a
144
+ # # => ["happy", "sad"]
145
+ def each_dictionary_value
146
+ return to_enum(__method__) {dictionary_size} unless block_given?
147
+
148
+ dictionary_size.times do |i|
149
+ yield dictionary_value_at(i)
150
+ end
151
+ end
109
152
  end
110
153
  end
@@ -52,7 +52,8 @@ module DuckDB
52
52
  end
53
53
 
54
54
  def pending_prepared_stream
55
- PendingResult.new(self, true)
55
+ warn("`#{self.class}##{__method__}` will be deprecated. use `#{self.class}#pending_prepared` instead")
56
+ pending_prepared
56
57
  end
57
58
 
58
59
  # returns statement type. The return value is one of the following symbols:
@@ -105,6 +106,46 @@ module DuckDB
105
106
  end
106
107
  end
107
108
 
109
+ # binds i-th parameter with SQL prepared statement.
110
+ # The first argument is index of parameter.
111
+ # The index of first parameter is 1 not 0.
112
+ # The second argument value is to expected Integer value between 0 to 255.
113
+ def bind_uint8(index, val)
114
+ return _bind_uint8(index, val) if val.between?(0, 255)
115
+
116
+ raise DuckDB::Error, "can't bind uint8(bind_uint8) to `#{val}`. The `#{val}` is out of range 0..255."
117
+ end
118
+
119
+ # binds i-th parameter with SQL prepared statement.
120
+ # The first argument is index of parameter.
121
+ # The index of first parameter is 1 not 0.
122
+ # The second argument value is to expected Integer value between 0 to 65535.
123
+ def bind_uint16(index, val)
124
+ return _bind_uint16(index, val) if val.between?(0, 65_535)
125
+
126
+ raise DuckDB::Error, "can't bind uint16(bind_uint16) to `#{val}`. The `#{val}` is out of range 0..65535."
127
+ end
128
+
129
+ # binds i-th parameter with SQL prepared statement.
130
+ # The first argument is index of parameter.
131
+ # The index of first parameter is 1 not 0.
132
+ # The second argument value is to expected Integer value between 0 to 4294967295.
133
+ def bind_uint32(index, val)
134
+ return _bind_uint32(index, val) if val.between?(0, 4_294_967_295)
135
+
136
+ raise DuckDB::Error, "can't bind uint32(bind_uint32) to `#{val}`. The `#{val}` is out of range 0..4294967295."
137
+ end
138
+
139
+ # binds i-th parameter with SQL prepared statement.
140
+ # The first argument is index of parameter.
141
+ # The index of first parameter is 1 not 0.
142
+ # The second argument value is to expected Integer value between 0 to 18446744073709551615.
143
+ def bind_uint64(index, val)
144
+ return _bind_uint64(index, val) if val.between?(0, 18_446_744_073_709_551_615)
145
+
146
+ raise DuckDB::Error, "can't bind uint64(bind_uint64) to `#{val}`. The `#{val}` is out of range 0..18446744073709551615."
147
+ end
148
+
108
149
  # binds i-th parameter with SQL prepared statement.
109
150
  # The first argument is index of parameter.
110
151
  # The index of first parameter is 1 not 0.
data/lib/duckdb/result.rb CHANGED
@@ -28,36 +28,16 @@ module DuckDB
28
28
 
29
29
  alias column_size column_count
30
30
 
31
- @use_chunk_each = false
32
-
33
31
  class << self
34
32
  def new
35
33
  raise DuckDB::Error, 'DuckDB::Result cannot be instantiated directly.'
36
34
  end
37
-
38
- attr_writer :use_chunk_each
39
-
40
- def use_chunk_each?
41
- @use_chunk_each
42
- end
43
35
  end
44
36
 
45
37
  def each(&)
46
- if self.class.use_chunk_each?
47
- return chunk_each unless block_given?
48
-
49
- chunk_each(&)
50
- else
51
- return _chunk_stream unless block_given?
52
-
53
- _chunk_stream(&)
54
- end
55
- end
38
+ return _chunk_stream unless block_given?
56
39
 
57
- # :nodoc:
58
- def chunk_each(&)
59
- warn 'DuckDB::Result#chunk_each will be deprecated.'
60
- _chunk_each(&)
40
+ _chunk_stream(&)
61
41
  end
62
42
 
63
43
  # returns return type. The return value is one of the following symbols:
@@ -3,5 +3,5 @@
3
3
  module DuckDB
4
4
  # The version string of ruby-duckdb.
5
5
  # Currently, ruby-duckdb is NOT semantic versioning.
6
- VERSION = '1.2.1.0'
6
+ VERSION = '1.3.0.0'
7
7
  end
data/lib/duckdb.rb CHANGED
@@ -15,6 +15,7 @@ require 'duckdb/config'
15
15
  require 'duckdb/column'
16
16
  require 'duckdb/logical_type'
17
17
  require 'duckdb/infinity'
18
+ require 'duckdb/instance_cache'
18
19
 
19
20
  # DuckDB provides Ruby interface of DuckDB.
20
21
  module DuckDB
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: duckdb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.1.0
4
+ version: 1.3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Suketa
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-29 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: bigdecimal
@@ -132,6 +132,8 @@ files:
132
132
  - ext/duckdb/extconf.rb
133
133
  - ext/duckdb/extracted_statements.c
134
134
  - ext/duckdb/extracted_statements.h
135
+ - ext/duckdb/instance_cache.c
136
+ - ext/duckdb/instance_cache.h
135
137
  - ext/duckdb/logical_type.c
136
138
  - ext/duckdb/logical_type.h
137
139
  - ext/duckdb/pending_result.c
@@ -154,6 +156,7 @@ files:
154
156
  - lib/duckdb/database.rb
155
157
  - lib/duckdb/extracted_statements.rb
156
158
  - lib/duckdb/infinity.rb
159
+ - lib/duckdb/instance_cache.rb
157
160
  - lib/duckdb/interval.rb
158
161
  - lib/duckdb/library_version.rb
159
162
  - lib/duckdb/logical_type.rb
@@ -185,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
185
188
  - !ruby/object:Gem::Version
186
189
  version: '0'
187
190
  requirements: []
188
- rubygems_version: 3.6.2
191
+ rubygems_version: 3.6.7
189
192
  specification_version: 4
190
193
  summary: This module is Ruby binding for DuckDB database engine.
191
194
  test_files: []