duckdb 1.3.1.0 → 1.4.1.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 +4 -4
- data/.github/workflows/test_on_macos.yml +2 -2
- data/.github/workflows/test_on_ubuntu.yml +2 -2
- data/.github/workflows/test_on_windows.yml +2 -2
- data/CHANGELOG.md +30 -0
- data/Gemfile.lock +10 -10
- data/duckdb.gemspec +1 -1
- data/ext/duckdb/appender.c +88 -4
- data/ext/duckdb/database.c +55 -7
- data/ext/duckdb/duckdb.c +2 -0
- data/ext/duckdb/extconf.rb +3 -0
- data/ext/duckdb/logical_type.c +34 -0
- data/ext/duckdb/logical_type.h +1 -1
- data/ext/duckdb/result.c +16 -2
- data/ext/duckdb/ruby-duckdb.h +8 -0
- data/ext/duckdb/scalar_function.c +57 -0
- data/ext/duckdb/scalar_function.h +14 -0
- data/ext/duckdb/value_impl.c +38 -0
- data/ext/duckdb/value_impl.h +13 -0
- data/getduckdb.sh +11 -3
- data/lib/duckdb/appender.rb +4 -0
- data/lib/duckdb/connection.rb +22 -0
- data/lib/duckdb/converter/int_to_sym.rb +5 -1
- data/lib/duckdb/logical_type.rb +49 -0
- data/lib/duckdb/version.rb +1 -1
- metadata +7 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 172cad0f5262bd839bcae9bd60455db2ae92c3d2777856a807448749b4982d63
|
|
4
|
+
data.tar.gz: 7af629371eb57967458add2ad62d88bf22f4c01eb3fc8e07ec67456c9d0edcb0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 92aa3a8b950008ff7327a27f98a76ba8e519d5f7ea1e3120b4d5310dd27bc15a7b330b5893d2a766da3533acf95a1e3b65614e28e9564a22286d8b493988fa9f
|
|
7
|
+
data.tar.gz: 53660ec068a0a15f6065d67c15323612d13b5e91fc578a81554a8e8728c92888096cf817d2649fc15d4af6bb1045ed9f4bdf2232cb67fd8701a4578c37c34e0a
|
|
@@ -15,8 +15,8 @@ jobs:
|
|
|
15
15
|
runs-on: macos-latest
|
|
16
16
|
strategy:
|
|
17
17
|
matrix:
|
|
18
|
-
ruby: ['3.2.
|
|
19
|
-
duckdb: ['1.
|
|
18
|
+
ruby: ['3.2.9', '3.3.10', '3.4.7', 'head', '3.5.0-preview1']
|
|
19
|
+
duckdb: ['1.4.1', '1.3.2']
|
|
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.2.
|
|
19
|
-
duckdb: ['1.
|
|
18
|
+
ruby: ['3.2.9', '3.3.10', '3.4.7', 'head', '3.5.0-preview1']
|
|
19
|
+
duckdb: ['1.4.1', '1.3.2']
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
22
|
- uses: actions/checkout@v4
|
|
@@ -15,8 +15,8 @@ jobs:
|
|
|
15
15
|
runs-on: windows-latest
|
|
16
16
|
strategy:
|
|
17
17
|
matrix:
|
|
18
|
-
ruby: ['3.2.
|
|
19
|
-
duckdb: ['1.
|
|
18
|
+
ruby: ['3.2.9', '3.3.10', '3.4.7', 'ucrt', 'mingw', 'mswin', 'head']
|
|
19
|
+
duckdb: ['1.4.1', '1.3.2']
|
|
20
20
|
|
|
21
21
|
steps:
|
|
22
22
|
- uses: actions/checkout@v4
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,36 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
# Unreleased
|
|
6
|
+
|
|
7
|
+
# 1.4.1.0 - 2025-11-01
|
|
8
|
+
- add DuckDB::Connection#appender_from_query.
|
|
9
|
+
- add DuckDB::Appender.create_query.
|
|
10
|
+
- add `DuckDB::LogicalType.boolean`, `DuckDB::LogicalType.tinyint`, `DuckDB::LogicalType.smallint`,
|
|
11
|
+
`DuckDB::LogicalType.integer`, `DuckDB::LogicalType.bigint`, `DuckDB::LogicalType.utinyint`,
|
|
12
|
+
`DuckDB::LogicalType.usmallint`, `DuckDB::LogicalType.uinteger`, `DuckDB::LogicalType.ubigint`,
|
|
13
|
+
`DuckDB::LogicalType.float`, `DuckDB::LogicalType.double`, `DuckDB::LogicalType.timestamp`,
|
|
14
|
+
`DuckDB::LogicalType.date`, `DuckDB::LogicalType.time`, `DuckDB::LogicalType.interval`,
|
|
15
|
+
`DuckDB::LogicalType.hugeint`, `DuckDB::LogicalType.uhugeint`, `DuckDB::LogicalType.varchar`,
|
|
16
|
+
`DuckDB::LogicalType.blob`, `DuckDB::LogicalType.timestamp_s`,
|
|
17
|
+
`DuckDB::LogicalType.timestamp_ms`, `DuckDB::LogicalType.timestamp_ns`,
|
|
18
|
+
`DuckDB::LogicalType.bit`, `DuckDB::LogicalType.time_tz`, `DuckDB::LogicalType.timestamp_tz`.
|
|
19
|
+
- add `DuckDB::LogicalType::BOOLEAN`, `DuckDB::LogicalType::TINYINT`, `DuckDB::LogicalType::SMALLINT`,
|
|
20
|
+
`DuckDB::LogicalType::INTEGER`, `DuckDB::LogicalType::BIGINT`, `DuckDB::LogicalType::UTINYINT`,
|
|
21
|
+
`DuckDB::LogicalType::USMALLINT`, `DuckDB::LogicalType::UINTEGER`, `DuckDB::LogicalType::UBIGINT`,
|
|
22
|
+
`DuckDB::LogicalType::FLOAT`, `DuckDB::LogicalType::DOUBLE`, `DuckDB::LogicalType::TIMESTAMP`,
|
|
23
|
+
`DuckDB::LogicalType::DATE`, `DuckDB::LogicalType::TIME`, `DuckDB::LogicalType::INTERVAL`,
|
|
24
|
+
`DuckDB::LogicalType::HUGEINT`, `DuckDB::LogicalType::UHUGEINT`, `DuckDB::LogicalType::VARCHAR`,
|
|
25
|
+
`DuckDB::LogicalType::BLOB`, `DuckDB::LogicalType::TIMESTAMP_S`,
|
|
26
|
+
`DuckDB::LogicalType::TIMESTAMP_MS`, `DuckDB::LogicalType::TIMESTAMP_NS`,
|
|
27
|
+
`DuckDB::LogicalType::BIT`, `DuckDB::LogicalType::TIME_TZ`, `DuckDB::LogicalType::TIMESTAMP_TZ`.
|
|
28
|
+
- Support TIMESTAMP_NS infinity, -infinity value.
|
|
29
|
+
- bump duckdb to 1.3.2, 1.4.1 on CI.
|
|
30
|
+
- add `DuckDB::ValueImpl` class. This class is under construction. You must not use this class directly.
|
|
31
|
+
- add `DuckDB::ScalarFunction` class. This class is under construction.
|
|
32
|
+
- add `DuckDB::ScalarFunction#set_name`.
|
|
33
|
+
- add `DuckDB::LogicalType.new(type_id)` to create a logical type from a type ID.
|
|
34
|
+
|
|
5
35
|
# 1.3.1.0 - 2025-06-28
|
|
6
36
|
- Support TIMESTAMP_S, TIMESTAMP_MS infinity, -infinity value.
|
|
7
37
|
- bump duckdb to 1.3.1 on CI.
|
data/Gemfile.lock
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
duckdb (1.
|
|
4
|
+
duckdb (1.4.1.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.
|
|
11
|
+
bigdecimal (3.3.1)
|
|
12
12
|
mini_portile2 (2.8.9)
|
|
13
|
-
minitest (5.
|
|
14
|
-
nokogiri (1.18.
|
|
13
|
+
minitest (5.26.0)
|
|
14
|
+
nokogiri (1.18.10)
|
|
15
15
|
mini_portile2 (~> 2.8.2)
|
|
16
16
|
racc (~> 1.4)
|
|
17
|
-
nokogiri (1.18.
|
|
17
|
+
nokogiri (1.18.10-aarch64-linux-gnu)
|
|
18
18
|
racc (~> 1.4)
|
|
19
|
-
nokogiri (1.18.
|
|
19
|
+
nokogiri (1.18.10-arm-linux-gnu)
|
|
20
20
|
racc (~> 1.4)
|
|
21
|
-
nokogiri (1.18.
|
|
21
|
+
nokogiri (1.18.10-arm64-darwin)
|
|
22
22
|
racc (~> 1.4)
|
|
23
|
-
nokogiri (1.18.
|
|
23
|
+
nokogiri (1.18.10-x86_64-darwin)
|
|
24
24
|
racc (~> 1.4)
|
|
25
|
-
nokogiri (1.18.
|
|
25
|
+
nokogiri (1.18.10-x86_64-linux-gnu)
|
|
26
26
|
racc (~> 1.4)
|
|
27
27
|
racc (1.8.1)
|
|
28
|
-
rake (13.3.
|
|
28
|
+
rake (13.3.1)
|
|
29
29
|
rake-compiler (1.3.0)
|
|
30
30
|
rake
|
|
31
31
|
ruby_memcheck (3.0.1)
|
data/duckdb.gemspec
CHANGED
|
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
|
|
|
27
27
|
end
|
|
28
28
|
spec.require_paths = ['lib']
|
|
29
29
|
spec.extensions = ['ext/duckdb/extconf.rb']
|
|
30
|
-
spec.required_ruby_version = '>= 3.
|
|
30
|
+
spec.required_ruby_version = '>= 3.2.0'
|
|
31
31
|
spec.add_dependency 'bigdecimal', '>= 3.1.4'
|
|
32
32
|
|
|
33
33
|
spec.add_development_dependency 'bundler', '~> 2.3'
|
data/ext/duckdb/appender.c
CHANGED
|
@@ -5,6 +5,11 @@ static VALUE cDuckDBAppender;
|
|
|
5
5
|
static void deallocate(void *);
|
|
6
6
|
static VALUE allocate(VALUE klass);
|
|
7
7
|
static size_t memsize(const void *p);
|
|
8
|
+
|
|
9
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
|
|
10
|
+
static VALUE appender_s_create_query(VALUE klass, VALUE con, VALUE query, VALUE types, VALUE table, VALUE columns);
|
|
11
|
+
#endif
|
|
12
|
+
|
|
8
13
|
static VALUE appender_initialize(VALUE klass, VALUE con, VALUE schema, VALUE table);
|
|
9
14
|
static VALUE appender_error_message(VALUE self);
|
|
10
15
|
static VALUE appender__append_bool(VALUE self, VALUE val);
|
|
@@ -56,6 +61,69 @@ static size_t memsize(const void *p) {
|
|
|
56
61
|
return sizeof(rubyDuckDBAppender);
|
|
57
62
|
}
|
|
58
63
|
|
|
64
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
|
|
65
|
+
/* call-seq:
|
|
66
|
+
* DuckDB::Appender.create_query -> DuckDB::Appender
|
|
67
|
+
*
|
|
68
|
+
* Returns a new Appender instance created from a query.
|
|
69
|
+
*
|
|
70
|
+
* require 'duckdb'
|
|
71
|
+
* db = DuckDB::Database.open
|
|
72
|
+
* con = db.connect
|
|
73
|
+
* con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
|
|
74
|
+
* query = 'INSERT OR REPLACE INTO users SELECT i, val FROM my_appended_data'
|
|
75
|
+
* types = [DuckDB::LogicalType::INTEGER, DuckDB::LogicalType::VARCHAR]
|
|
76
|
+
* appender = DuckDB::Appender.create_query(con, query, types, 'my_appended_data', %w[i val])
|
|
77
|
+
*/
|
|
78
|
+
static VALUE appender_s_create_query(VALUE klass, VALUE con, VALUE query, VALUE types, VALUE table, VALUE columns) {
|
|
79
|
+
rubyDuckDBConnection *ctxcon;
|
|
80
|
+
rubyDuckDBAppender *ctx;
|
|
81
|
+
char *query_str = StringValuePtr(query);
|
|
82
|
+
char *table_name = NULL;
|
|
83
|
+
const char **column_names = NULL;
|
|
84
|
+
idx_t column_count = 0;
|
|
85
|
+
duckdb_logical_type *type_array = NULL;
|
|
86
|
+
VALUE appender = Qnil;
|
|
87
|
+
|
|
88
|
+
if (!rb_obj_is_kind_of(con, cDuckDBConnection)) {
|
|
89
|
+
rb_raise(rb_eTypeError, "1st argument should be instance of DackDB::Connection");
|
|
90
|
+
}
|
|
91
|
+
if (rb_obj_is_kind_of(types, rb_cArray) == Qfalse) {
|
|
92
|
+
rb_raise(rb_eTypeError, "2nd argument should be an Array");
|
|
93
|
+
}
|
|
94
|
+
column_count = RARRAY_LEN(types);
|
|
95
|
+
type_array = ALLOCA_N(duckdb_logical_type, (size_t)column_count);
|
|
96
|
+
for (idx_t i = 0; i < column_count; i++) {
|
|
97
|
+
VALUE type_val = rb_ary_entry(types, i);
|
|
98
|
+
rubyDuckDBLogicalType *type_ctx = get_struct_logical_type(type_val);
|
|
99
|
+
type_array[i] = type_ctx->logical_type;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if (table != Qnil) {
|
|
103
|
+
table_name = StringValuePtr(table);
|
|
104
|
+
}
|
|
105
|
+
if (columns != Qnil) {
|
|
106
|
+
if (rb_obj_is_kind_of(columns, rb_cArray) == Qfalse) {
|
|
107
|
+
rb_raise(rb_eTypeError, "4th argument should be an Array or nil");
|
|
108
|
+
}
|
|
109
|
+
idx_t col_count = RARRAY_LEN(columns);
|
|
110
|
+
column_names = ALLOCA_N(const char *, (size_t)col_count);
|
|
111
|
+
for (idx_t i = 0; i < col_count; i++) {
|
|
112
|
+
VALUE col_name_val = rb_ary_entry(columns, i);
|
|
113
|
+
column_names[i] = StringValuePtr(col_name_val);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
ctxcon = get_struct_connection(con);
|
|
117
|
+
appender = allocate(klass);
|
|
118
|
+
TypedData_Get_Struct(appender, rubyDuckDBAppender, &appender_data_type, ctx);
|
|
119
|
+
if (duckdb_appender_create_query(ctxcon->con, query_str, column_count, type_array, table_name, column_names, &ctx->appender) == DuckDBError) {
|
|
120
|
+
rb_raise(eDuckDBError, "failed to create appender from query");
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return appender;
|
|
124
|
+
}
|
|
125
|
+
#endif
|
|
126
|
+
|
|
59
127
|
static VALUE appender_initialize(VALUE self, VALUE con, VALUE schema, VALUE table) {
|
|
60
128
|
|
|
61
129
|
rubyDuckDBConnection *ctxcon;
|
|
@@ -93,14 +161,27 @@ static VALUE appender_initialize(VALUE self, VALUE con, VALUE schema, VALUE tabl
|
|
|
93
161
|
*/
|
|
94
162
|
static VALUE appender_error_message(VALUE self) {
|
|
95
163
|
rubyDuckDBAppender *ctx;
|
|
96
|
-
|
|
164
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
|
|
165
|
+
duckdb_error_data error_data;
|
|
166
|
+
#endif
|
|
167
|
+
const char *msg = NULL;
|
|
168
|
+
VALUE rb_msg = Qnil;
|
|
97
169
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
|
98
170
|
|
|
171
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
|
|
172
|
+
error_data = duckdb_appender_error_data(ctx->appender);
|
|
173
|
+
if (duckdb_error_data_has_error(error_data)) {
|
|
174
|
+
msg = duckdb_error_data_message(error_data);
|
|
175
|
+
rb_msg = rb_str_new2(msg);
|
|
176
|
+
}
|
|
177
|
+
duckdb_destroy_error_data(&error_data);
|
|
178
|
+
#else
|
|
99
179
|
msg = duckdb_appender_error(ctx->appender);
|
|
100
|
-
if (msg
|
|
101
|
-
|
|
180
|
+
if (msg != NULL) {
|
|
181
|
+
rb_msg = rb_str_new2(msg);
|
|
102
182
|
}
|
|
103
|
-
|
|
183
|
+
#endif
|
|
184
|
+
return rb_msg;
|
|
104
185
|
}
|
|
105
186
|
|
|
106
187
|
/* :nodoc: */
|
|
@@ -376,6 +457,9 @@ void rbduckdb_init_duckdb_appender(void) {
|
|
|
376
457
|
#endif
|
|
377
458
|
cDuckDBAppender = rb_define_class_under(mDuckDB, "Appender", rb_cObject);
|
|
378
459
|
rb_define_alloc_func(cDuckDBAppender, allocate);
|
|
460
|
+
#ifdef HAVE_DUCKDB_H_GE_V1_4_0
|
|
461
|
+
rb_define_singleton_method(cDuckDBAppender, "create_query", appender_s_create_query, 5);
|
|
462
|
+
#endif
|
|
379
463
|
rb_define_method(cDuckDBAppender, "initialize", appender_initialize, 3);
|
|
380
464
|
rb_define_method(cDuckDBAppender, "error_message", appender_error_message, 0);
|
|
381
465
|
rb_define_private_method(cDuckDBAppender, "_end_row", appender__end_row, 0);
|
data/ext/duckdb/database.c
CHANGED
|
@@ -6,6 +6,7 @@ static void close_database(rubyDuckDB *p);
|
|
|
6
6
|
static void deallocate(void * ctx);
|
|
7
7
|
static VALUE allocate(VALUE klass);
|
|
8
8
|
static size_t memsize(const void *p);
|
|
9
|
+
static duckdb_config create_config_with_ruby_api(void);
|
|
9
10
|
static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase);
|
|
10
11
|
static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBDatabase);
|
|
11
12
|
static VALUE duckdb_database_connect(VALUE self);
|
|
@@ -43,10 +44,27 @@ rubyDuckDB *rbduckdb_get_struct_database(VALUE obj) {
|
|
|
43
44
|
return ctx;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
static duckdb_config create_config_with_ruby_api(void) {
|
|
48
|
+
duckdb_config config;
|
|
49
|
+
|
|
50
|
+
if (duckdb_create_config(&config) == DuckDBError) {
|
|
51
|
+
rb_raise(eDuckDBError, "failed to create config");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (duckdb_set_config(config, "duckdb_api", "ruby") == DuckDBError) {
|
|
55
|
+
duckdb_destroy_config(&config);
|
|
56
|
+
rb_raise(eDuckDBError, "failed to set duckdb_api config");
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return config;
|
|
60
|
+
}
|
|
61
|
+
|
|
46
62
|
/* :nodoc: */
|
|
47
63
|
static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase) {
|
|
48
64
|
rubyDuckDB *ctx;
|
|
49
65
|
VALUE obj;
|
|
66
|
+
duckdb_config config;
|
|
67
|
+
char *perror = NULL;
|
|
50
68
|
|
|
51
69
|
char *pfile = NULL;
|
|
52
70
|
VALUE file = Qnil;
|
|
@@ -59,9 +77,19 @@ static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase
|
|
|
59
77
|
|
|
60
78
|
obj = allocate(cDuckDBDatabase);
|
|
61
79
|
TypedData_Get_Struct(obj, rubyDuckDB, &database_data_type, ctx);
|
|
62
|
-
|
|
63
|
-
|
|
80
|
+
|
|
81
|
+
config = create_config_with_ruby_api();
|
|
82
|
+
|
|
83
|
+
if (duckdb_open_ext(pfile, &(ctx->db), config, &perror) == DuckDBError) {
|
|
84
|
+
VALUE error_msg = rb_str_new_cstr(perror ? perror : "Unknown error");
|
|
85
|
+
if (perror) {
|
|
86
|
+
duckdb_free(perror);
|
|
87
|
+
}
|
|
88
|
+
duckdb_destroy_config(&config);
|
|
89
|
+
rb_raise(eDuckDBError, "failed to open database: %s", StringValueCStr(error_msg));
|
|
64
90
|
}
|
|
91
|
+
|
|
92
|
+
duckdb_destroy_config(&config);
|
|
65
93
|
return obj;
|
|
66
94
|
}
|
|
67
95
|
|
|
@@ -70,7 +98,9 @@ static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBData
|
|
|
70
98
|
rubyDuckDB *ctx;
|
|
71
99
|
VALUE obj;
|
|
72
100
|
rubyDuckDBConfig *ctx_config;
|
|
73
|
-
|
|
101
|
+
duckdb_config config_to_use;
|
|
102
|
+
char *perror = NULL;
|
|
103
|
+
int need_destroy_config = 0;
|
|
74
104
|
|
|
75
105
|
char *pfile = NULL;
|
|
76
106
|
VALUE file = Qnil;
|
|
@@ -84,19 +114,37 @@ static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBData
|
|
|
84
114
|
|
|
85
115
|
obj = allocate(cDuckDBDatabase);
|
|
86
116
|
TypedData_Get_Struct(obj, rubyDuckDB, &database_data_type, ctx);
|
|
117
|
+
|
|
87
118
|
if (!NIL_P(config)) {
|
|
88
119
|
if (!rb_obj_is_kind_of(config, cDuckDBConfig)) {
|
|
89
120
|
rb_raise(rb_eTypeError, "The second argument must be DuckDB::Config object.");
|
|
90
121
|
}
|
|
91
122
|
ctx_config = get_struct_config(config);
|
|
92
|
-
|
|
93
|
-
|
|
123
|
+
/* Set duckdb_api to "ruby" for the provided config */
|
|
124
|
+
if (duckdb_set_config(ctx_config->config, "duckdb_api", "ruby") == DuckDBError) {
|
|
125
|
+
rb_raise(eDuckDBError, "failed to set duckdb_api config");
|
|
94
126
|
}
|
|
127
|
+
config_to_use = ctx_config->config;
|
|
95
128
|
} else {
|
|
96
|
-
|
|
97
|
-
|
|
129
|
+
config_to_use = create_config_with_ruby_api();
|
|
130
|
+
need_destroy_config = 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (duckdb_open_ext(pfile, &(ctx->db), config_to_use, &perror) == DuckDBError) {
|
|
134
|
+
VALUE error_msg = rb_str_new_cstr(perror ? perror : "Unknown error");
|
|
135
|
+
if (perror) {
|
|
136
|
+
duckdb_free(perror);
|
|
98
137
|
}
|
|
138
|
+
if (need_destroy_config) {
|
|
139
|
+
duckdb_destroy_config(&config_to_use);
|
|
140
|
+
}
|
|
141
|
+
rb_raise(eDuckDBError, "failed to open database: %s", StringValueCStr(error_msg));
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (need_destroy_config) {
|
|
145
|
+
duckdb_destroy_config(&config_to_use);
|
|
99
146
|
}
|
|
147
|
+
|
|
100
148
|
return obj;
|
|
101
149
|
}
|
|
102
150
|
|
data/ext/duckdb/duckdb.c
CHANGED
data/ext/duckdb/extconf.rb
CHANGED
|
@@ -64,6 +64,9 @@ have_func('duckdb_create_instance_cache', 'duckdb.h')
|
|
|
64
64
|
# check duckdb >= 1.3.0
|
|
65
65
|
have_func('duckdb_get_table_names', 'duckdb.h')
|
|
66
66
|
|
|
67
|
+
# check duckdb >= 1.4.0
|
|
68
|
+
have_func('duckdb_appender_create_query', 'duckdb.h')
|
|
69
|
+
|
|
67
70
|
$CFLAGS << ' -DDUCKDB_API_NO_DEPRECATED' if ENV['DUCKDB_API_NO_DEPRECATED']
|
|
68
71
|
|
|
69
72
|
create_makefile('duckdb/duckdb_native')
|
data/ext/duckdb/logical_type.c
CHANGED
|
@@ -23,6 +23,7 @@ static VALUE duckdb_logical_type_dictionary_size(VALUE self);
|
|
|
23
23
|
static VALUE duckdb_logical_type_dictionary_value_at(VALUE self, VALUE didx);
|
|
24
24
|
static VALUE duckdb_logical_type__get_alias(VALUE self);
|
|
25
25
|
static VALUE duckdb_logical_type__set_alias(VALUE self, VALUE aname);
|
|
26
|
+
static VALUE initialize(VALUE self, VALUE type_id_arg);
|
|
26
27
|
|
|
27
28
|
static const rb_data_type_t logical_type_data_type = {
|
|
28
29
|
"DuckDB/LogicalType",
|
|
@@ -40,6 +41,12 @@ static void deallocate(void *ctx) {
|
|
|
40
41
|
xfree(p);
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
rubyDuckDBLogicalType *get_struct_logical_type(VALUE obj) {
|
|
45
|
+
rubyDuckDBLogicalType *ctx;
|
|
46
|
+
TypedData_Get_Struct(obj, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
|
|
47
|
+
return ctx;
|
|
48
|
+
}
|
|
49
|
+
|
|
43
50
|
static VALUE allocate(VALUE klass) {
|
|
44
51
|
rubyDuckDBLogicalType *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBLogicalType));
|
|
45
52
|
return TypedData_Wrap_Struct(klass, &logical_type_data_type, ctx);
|
|
@@ -49,6 +56,31 @@ static size_t memsize(const void *p) {
|
|
|
49
56
|
return sizeof(rubyDuckDBLogicalType);
|
|
50
57
|
}
|
|
51
58
|
|
|
59
|
+
static VALUE initialize(VALUE self, VALUE type_id_arg) {
|
|
60
|
+
rubyDuckDBLogicalType *ctx;
|
|
61
|
+
duckdb_type type = (duckdb_type)NUM2INT(type_id_arg);
|
|
62
|
+
duckdb_logical_type new_logical_type;
|
|
63
|
+
|
|
64
|
+
TypedData_Get_Struct(self, rubyDuckDBLogicalType, &logical_type_data_type, ctx);
|
|
65
|
+
|
|
66
|
+
if (ctx->logical_type) {
|
|
67
|
+
duckdb_destroy_logical_type(&(ctx->logical_type));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
new_logical_type = duckdb_create_logical_type(type);
|
|
71
|
+
|
|
72
|
+
if (!new_logical_type || duckdb_get_type_id(new_logical_type) == DUCKDB_TYPE_INVALID) {
|
|
73
|
+
if (new_logical_type) {
|
|
74
|
+
duckdb_destroy_logical_type(&new_logical_type);
|
|
75
|
+
}
|
|
76
|
+
rb_raise(rb_eArgError, "Invalid or unsupported logical type ID: %d", type);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
ctx->logical_type = new_logical_type;
|
|
80
|
+
|
|
81
|
+
return self;
|
|
82
|
+
}
|
|
83
|
+
|
|
52
84
|
/*
|
|
53
85
|
* call-seq:
|
|
54
86
|
* decimal_col.logical_type.type -> Symbol
|
|
@@ -439,4 +471,6 @@ void rbduckdb_init_duckdb_logical_type(void) {
|
|
|
439
471
|
rb_define_method(cDuckDBLogicalType, "dictionary_value_at", duckdb_logical_type_dictionary_value_at, 1);
|
|
440
472
|
rb_define_method(cDuckDBLogicalType, "get_alias", duckdb_logical_type__get_alias, 0);
|
|
441
473
|
rb_define_method(cDuckDBLogicalType, "set_alias", duckdb_logical_type__set_alias, 1);
|
|
474
|
+
|
|
475
|
+
rb_define_method(cDuckDBLogicalType, "initialize", initialize, 1);
|
|
442
476
|
}
|
data/ext/duckdb/logical_type.h
CHANGED
data/ext/duckdb/result.c
CHANGED
|
@@ -50,6 +50,7 @@ static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row
|
|
|
50
50
|
static VALUE infinite_timestamp_value(duckdb_timestamp timestamp);
|
|
51
51
|
static VALUE infinite_timestamp_s_value(duckdb_timestamp_s timestamp_s);
|
|
52
52
|
static VALUE infinite_timestamp_ms_value(duckdb_timestamp_ms timestamp_ms);
|
|
53
|
+
static VALUE infinite_timestamp_ns_value(duckdb_timestamp_ns timestamp_ns);
|
|
53
54
|
|
|
54
55
|
static VALUE vector_timestamp_s(void* vector_data, idx_t row_idx);
|
|
55
56
|
static VALUE vector_timestamp_ms(void* vector_data, idx_t row_idx);
|
|
@@ -474,10 +475,23 @@ static VALUE vector_timestamp_ms(void* vector_data, idx_t row_idx) {
|
|
|
474
475
|
);
|
|
475
476
|
}
|
|
476
477
|
|
|
478
|
+
static VALUE infinite_timestamp_ns_value(duckdb_timestamp_ns timestamp_ns) {
|
|
479
|
+
if (duckdb_is_finite_timestamp_ns(timestamp_ns) == false) {
|
|
480
|
+
return rb_funcall(mDuckDBConverter, id__to_infinity, 1,
|
|
481
|
+
LL2NUM(timestamp_ns.nanos)
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
return Qnil;
|
|
485
|
+
}
|
|
486
|
+
|
|
477
487
|
static VALUE vector_timestamp_ns(void* vector_data, idx_t row_idx) {
|
|
478
|
-
|
|
488
|
+
duckdb_timestamp_ns data = ((duckdb_timestamp_ns *)vector_data)[row_idx];
|
|
489
|
+
VALUE obj = infinite_timestamp_ns_value(data);
|
|
490
|
+
if (obj != Qnil) {
|
|
491
|
+
return obj;
|
|
492
|
+
}
|
|
479
493
|
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_timestamp_ns, 1,
|
|
480
|
-
LL2NUM(data.
|
|
494
|
+
LL2NUM(data.nanos)
|
|
481
495
|
);
|
|
482
496
|
}
|
|
483
497
|
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
|
@@ -12,6 +12,10 @@
|
|
|
12
12
|
#define HAVE_DUCKDB_H_GE_V1_3_0 1
|
|
13
13
|
#endif
|
|
14
14
|
|
|
15
|
+
#ifdef HAVE_DUCKDB_APPENDER_CREATE_QUERY
|
|
16
|
+
#define HAVE_DUCKDB_H_GE_V1_4_0 1
|
|
17
|
+
#endif
|
|
18
|
+
|
|
15
19
|
#include "./error.h"
|
|
16
20
|
#include "./database.h"
|
|
17
21
|
#include "./connection.h"
|
|
@@ -28,6 +32,8 @@
|
|
|
28
32
|
#include "./appender.h"
|
|
29
33
|
#include "./config.h"
|
|
30
34
|
#include "./instance_cache.h"
|
|
35
|
+
#include "./value_impl.h"
|
|
36
|
+
#include "./scalar_function.h"
|
|
31
37
|
|
|
32
38
|
extern VALUE mDuckDB;
|
|
33
39
|
extern VALUE cDuckDBDatabase;
|
|
@@ -40,5 +46,7 @@ extern VALUE cDuckDBPreparedStatement;
|
|
|
40
46
|
extern VALUE PositiveInfinity;
|
|
41
47
|
extern VALUE NegativeInfinity;
|
|
42
48
|
extern VALUE cDuckDBInstanceCache;
|
|
49
|
+
extern VALUE cDuckDBValueImpl;
|
|
50
|
+
extern VALUE cDuckDBScalarFunction;
|
|
43
51
|
|
|
44
52
|
#endif
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#include "ruby-duckdb.h"
|
|
2
|
+
|
|
3
|
+
VALUE cDuckDBScalarFunction;
|
|
4
|
+
|
|
5
|
+
static void deallocate(void *);
|
|
6
|
+
static VALUE allocate(VALUE klass);
|
|
7
|
+
static size_t memsize(const void *p);
|
|
8
|
+
static VALUE duckdb_scalar_function_initialize(VALUE self);
|
|
9
|
+
static VALUE rbduckdb_scalar_function_set_name(VALUE self, VALUE name);
|
|
10
|
+
|
|
11
|
+
static const rb_data_type_t scalar_function_data_type = {
|
|
12
|
+
"DuckDB/ScalarFunction",
|
|
13
|
+
{NULL, deallocate, memsize,},
|
|
14
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
static void deallocate(void * ctx) {
|
|
18
|
+
rubyDuckDBScalarFunction *p = (rubyDuckDBScalarFunction *)ctx;
|
|
19
|
+
duckdb_destroy_scalar_function(&(p->scalar_function));
|
|
20
|
+
xfree(p);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
static VALUE allocate(VALUE klass) {
|
|
24
|
+
rubyDuckDBScalarFunction *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBScalarFunction));
|
|
25
|
+
return TypedData_Wrap_Struct(klass, &scalar_function_data_type, ctx);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
static size_t memsize(const void *p) {
|
|
29
|
+
return sizeof(rubyDuckDBScalarFunction);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
static VALUE duckdb_scalar_function_initialize(VALUE self) {
|
|
33
|
+
rubyDuckDBScalarFunction *p;
|
|
34
|
+
TypedData_Get_Struct(self, rubyDuckDBScalarFunction, &scalar_function_data_type, p);
|
|
35
|
+
p->scalar_function = duckdb_create_scalar_function();
|
|
36
|
+
return self;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
static VALUE rbduckdb_scalar_function_set_name(VALUE self, VALUE name) {
|
|
40
|
+
rubyDuckDBScalarFunction *p;
|
|
41
|
+
TypedData_Get_Struct(self, rubyDuckDBScalarFunction, &scalar_function_data_type, p);
|
|
42
|
+
|
|
43
|
+
const char *str = StringValuePtr(name);
|
|
44
|
+
duckdb_scalar_function_set_name(p->scalar_function, str);
|
|
45
|
+
|
|
46
|
+
return self;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
void rbduckdb_init_duckdb_scalar_function(void) {
|
|
50
|
+
#if 0
|
|
51
|
+
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
52
|
+
#endif
|
|
53
|
+
cDuckDBScalarFunction = rb_define_class_under(mDuckDB, "ScalarFunction", rb_cObject);
|
|
54
|
+
rb_define_alloc_func(cDuckDBScalarFunction, allocate);
|
|
55
|
+
rb_define_method(cDuckDBScalarFunction, "initialize", duckdb_scalar_function_initialize, 0);
|
|
56
|
+
rb_define_method(cDuckDBScalarFunction, "set_name", rbduckdb_scalar_function_set_name, 1);
|
|
57
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#ifndef RUBY_DUCKDB_SCALAR_FUNCTION_H
|
|
2
|
+
#define RUBY_DUCKDB_SCALAR_FUNCTION_H
|
|
3
|
+
|
|
4
|
+
struct _rubyDuckDBScalarFunction {
|
|
5
|
+
duckdb_scalar_function scalar_function;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
typedef struct _rubyDuckDBScalarFunction rubyDuckDBScalarFunction;
|
|
9
|
+
|
|
10
|
+
void rbduckdb_init_duckdb_scalar_function(void);
|
|
11
|
+
|
|
12
|
+
#endif
|
|
13
|
+
|
|
14
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#include "ruby-duckdb.h"
|
|
2
|
+
|
|
3
|
+
VALUE cDuckDBValueImpl;
|
|
4
|
+
|
|
5
|
+
static void deallocate(void *);
|
|
6
|
+
static VALUE allocate(VALUE klass);
|
|
7
|
+
static size_t memsize(const void *p);
|
|
8
|
+
|
|
9
|
+
static const rb_data_type_t value_impl_data_type = {
|
|
10
|
+
"DuckDB/ValueImpl",
|
|
11
|
+
{NULL, deallocate, memsize,},
|
|
12
|
+
0, 0, RUBY_TYPED_FREE_IMMEDIATELY
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
static void deallocate(void * ctx) {
|
|
16
|
+
rubyDuckDBValueImpl *p = (rubyDuckDBValueImpl *)ctx;
|
|
17
|
+
|
|
18
|
+
duckdb_destroy_value(&(p->value));
|
|
19
|
+
xfree(p);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
static VALUE allocate(VALUE klass) {
|
|
23
|
+
rubyDuckDBValueImpl *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBValueImpl));
|
|
24
|
+
return TypedData_Wrap_Struct(klass, &value_impl_data_type, ctx);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
static size_t memsize(const void *p) {
|
|
28
|
+
return sizeof(rubyDuckDBValueImpl);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
void rbduckdb_init_duckdb_value_impl(void) {
|
|
32
|
+
#if 0
|
|
33
|
+
VALUE mDuckDB = rb_define_module("DuckDB");
|
|
34
|
+
#endif
|
|
35
|
+
cDuckDBValueImpl = rb_define_class_under(mDuckDB, "ValueImpl", rb_cObject);
|
|
36
|
+
rb_define_alloc_func(cDuckDBValueImpl, allocate);
|
|
37
|
+
}
|
|
38
|
+
|
data/getduckdb.sh
CHANGED
|
@@ -3,8 +3,16 @@
|
|
|
3
3
|
MACHINE=`uname -m`
|
|
4
4
|
|
|
5
5
|
case "$MACHINE" in
|
|
6
|
-
"x86_64"
|
|
7
|
-
|
|
6
|
+
"x86_64")
|
|
7
|
+
ARCH=amd64
|
|
8
|
+
;;
|
|
9
|
+
"aarch64")
|
|
10
|
+
if printf '%s\n' '1.3.0' "$DUCKDB_VERSION" | sort -C -V; then
|
|
11
|
+
ARCH=arm64
|
|
12
|
+
else
|
|
13
|
+
ARCH=aarch64
|
|
14
|
+
fi
|
|
15
|
+
;;
|
|
8
16
|
esac
|
|
9
17
|
|
|
10
|
-
wget -O duckdb.zip "https://github.com/duckdb/duckdb/releases/download/v$DUCKDB_VERSION/libduckdb-linux-$
|
|
18
|
+
wget -O duckdb.zip "https://github.com/duckdb/duckdb/releases/download/v$DUCKDB_VERSION/libduckdb-linux-$ARCH.zip"
|
data/lib/duckdb/appender.rb
CHANGED
|
@@ -23,6 +23,10 @@ module DuckDB
|
|
|
23
23
|
private_constant :RANGE_INT16, :RANGE_INT32, :RANGE_INT64
|
|
24
24
|
# :startdoc:
|
|
25
25
|
|
|
26
|
+
class << self
|
|
27
|
+
alias from_query create_query if DuckDB::Appender.respond_to?(:create_query)
|
|
28
|
+
end
|
|
29
|
+
|
|
26
30
|
# :call-seq:
|
|
27
31
|
# appender.begin_row -> self
|
|
28
32
|
# A nop method, provided for backwards compatibility reasons.
|
data/lib/duckdb/connection.rb
CHANGED
|
@@ -136,6 +136,28 @@ module DuckDB
|
|
|
136
136
|
appender.close
|
|
137
137
|
end
|
|
138
138
|
|
|
139
|
+
if Appender.respond_to?(:create_query)
|
|
140
|
+
# :call-seq:
|
|
141
|
+
# connection.appender_from_query(query, types, table_name = nil, column_names = nil) -> DuckDB::Appender
|
|
142
|
+
#
|
|
143
|
+
# Creates an appender object that executes the given query with any data appended to it.
|
|
144
|
+
# The `table_name` parameter is used to refer to the appended data in the query. If omitted, it defaults to "appended_data".
|
|
145
|
+
# The `column_names` parameter provides names for the columns of the appended data. If omitted, it defaults to "col1", "col2", etc.
|
|
146
|
+
#
|
|
147
|
+
# require 'duckdb'
|
|
148
|
+
# db = DuckDB::Database.open
|
|
149
|
+
# con = db.connect
|
|
150
|
+
# con.query('CREATE TABLE t (i INT PRIMARY KEY, value VARCHAR)')
|
|
151
|
+
# query = 'INSERT OR REPLACE INTO t SELECT i, val FROM my_appended_data'
|
|
152
|
+
# types = [DuckDB::LogicalType::INTEGER, DuckDB::LogicalType::VARCHAR]
|
|
153
|
+
# appender = con.appender_from_query(query, types, 'my_appended_data', %w[i val])
|
|
154
|
+
# appender.append_row(1, 'hello world')
|
|
155
|
+
# appender.close
|
|
156
|
+
def appender_from_query(query, types, table_name = nil, column_names = nil)
|
|
157
|
+
Appender.create_query(self, query, types, table_name, column_names)
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
139
161
|
private
|
|
140
162
|
|
|
141
163
|
def create_appender(table)
|
data/lib/duckdb/logical_type.rb
CHANGED
|
@@ -5,6 +5,55 @@ module DuckDB
|
|
|
5
5
|
alias :alias get_alias
|
|
6
6
|
alias :alias= set_alias
|
|
7
7
|
|
|
8
|
+
@logical_types = {}
|
|
9
|
+
|
|
10
|
+
{
|
|
11
|
+
boolean: 1,
|
|
12
|
+
tinyint: 2,
|
|
13
|
+
smallint: 3,
|
|
14
|
+
integer: 4,
|
|
15
|
+
bigint: 5,
|
|
16
|
+
utinyint: 6,
|
|
17
|
+
usmallint: 7,
|
|
18
|
+
uinteger: 8,
|
|
19
|
+
ubigint: 9,
|
|
20
|
+
float: 10,
|
|
21
|
+
double: 11,
|
|
22
|
+
timestamp: 12,
|
|
23
|
+
date: 13,
|
|
24
|
+
time: 14,
|
|
25
|
+
interval: 15,
|
|
26
|
+
hugeint: 16,
|
|
27
|
+
uhugeint: 32,
|
|
28
|
+
varchar: 17,
|
|
29
|
+
blob: 18,
|
|
30
|
+
# decimal: 19,
|
|
31
|
+
timestamp_s: 20,
|
|
32
|
+
timestamp_ms: 21,
|
|
33
|
+
timestamp_ns: 22,
|
|
34
|
+
# enum: 23,
|
|
35
|
+
# list: 24,
|
|
36
|
+
# struct: 25,
|
|
37
|
+
# map: 26,
|
|
38
|
+
# array: 33,
|
|
39
|
+
# uuid: 27,
|
|
40
|
+
# union: 28,
|
|
41
|
+
bit: 29,
|
|
42
|
+
time_tz: 30,
|
|
43
|
+
timestamp_tz: 31,
|
|
44
|
+
any: 34,
|
|
45
|
+
bignum: 35,
|
|
46
|
+
sqlnull: 36,
|
|
47
|
+
string_literal: 37,
|
|
48
|
+
integer_literal: 38
|
|
49
|
+
# time_ns: 39
|
|
50
|
+
}.each do |method_name, type_id|
|
|
51
|
+
define_singleton_method(method_name) do
|
|
52
|
+
@logical_types[type_id] ||= DuckDB::LogicalType.new(type_id)
|
|
53
|
+
end
|
|
54
|
+
const_set(method_name.upcase, send(method_name))
|
|
55
|
+
end
|
|
56
|
+
|
|
8
57
|
# returns logical type's type symbol
|
|
9
58
|
# `:unknown` means that the logical type's type is unknown/unsupported by ruby-duckdb.
|
|
10
59
|
# `:invalid` means that the logical type's type is invalid in duckdb.
|
data/lib/duckdb/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: duckdb
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.4.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Masaki Suketa
|
|
@@ -143,8 +143,12 @@ files:
|
|
|
143
143
|
- ext/duckdb/result.c
|
|
144
144
|
- ext/duckdb/result.h
|
|
145
145
|
- ext/duckdb/ruby-duckdb.h
|
|
146
|
+
- ext/duckdb/scalar_function.c
|
|
147
|
+
- ext/duckdb/scalar_function.h
|
|
146
148
|
- ext/duckdb/util.c
|
|
147
149
|
- ext/duckdb/util.h
|
|
150
|
+
- ext/duckdb/value_impl.c
|
|
151
|
+
- ext/duckdb/value_impl.h
|
|
148
152
|
- getduckdb.sh
|
|
149
153
|
- lib/duckdb.rb
|
|
150
154
|
- lib/duckdb/appender.rb
|
|
@@ -181,14 +185,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
181
185
|
requirements:
|
|
182
186
|
- - ">="
|
|
183
187
|
- !ruby/object:Gem::Version
|
|
184
|
-
version: 3.
|
|
188
|
+
version: 3.2.0
|
|
185
189
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
186
190
|
requirements:
|
|
187
191
|
- - ">="
|
|
188
192
|
- !ruby/object:Gem::Version
|
|
189
193
|
version: '0'
|
|
190
194
|
requirements: []
|
|
191
|
-
rubygems_version: 3.6.
|
|
195
|
+
rubygems_version: 3.6.9
|
|
192
196
|
specification_version: 4
|
|
193
197
|
summary: This module is Ruby binding for DuckDB database engine.
|
|
194
198
|
test_files: []
|