duckdb 0.9.1.1 → 0.9.2
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/.gitattributes +1 -0
- data/.github/workflows/test_on_macos.yml +6 -6
- data/.github/workflows/test_on_ubuntu.yml +6 -6
- data/.github/workflows/test_on_windows.yml +4 -4
- data/CHANGELOG.md +11 -0
- data/Dockerfile +1 -1
- data/Gemfile.lock +5 -5
- data/README.md +17 -1
- data/benchmark/async_query.rb +90 -0
- data/ext/duckdb/appender.c +5 -5
- data/ext/duckdb/appender.h +1 -1
- data/ext/duckdb/blob.c +1 -1
- data/ext/duckdb/blob.h +1 -4
- data/ext/duckdb/column.c +2 -2
- data/ext/duckdb/column.h +2 -2
- data/ext/duckdb/config.c +1 -1
- data/ext/duckdb/config.h +1 -1
- data/ext/duckdb/connection.c +66 -6
- data/ext/duckdb/connection.h +2 -2
- data/ext/duckdb/converter.h +1 -1
- data/ext/duckdb/conveter.c +1 -1
- data/ext/duckdb/database.c +3 -3
- data/ext/duckdb/database.h +2 -2
- data/ext/duckdb/duckdb.c +11 -11
- data/ext/duckdb/error.c +1 -1
- data/ext/duckdb/error.h +1 -1
- data/ext/duckdb/extconf.rb +46 -13
- data/ext/duckdb/pending_result.c +45 -6
- data/ext/duckdb/pending_result.h +1 -1
- data/ext/duckdb/prepared_statement.c +7 -7
- data/ext/duckdb/prepared_statement.h +1 -1
- data/ext/duckdb/result.c +112 -70
- data/ext/duckdb/result.h +2 -2
- data/ext/duckdb/ruby-duckdb.h +1 -0
- data/ext/duckdb/util.c +4 -4
- data/ext/duckdb/util.h +4 -4
- data/lib/duckdb/appender.rb +1 -10
- data/lib/duckdb/connection.rb +50 -8
- data/lib/duckdb/converter.rb +27 -1
- data/lib/duckdb/prepared_statement.rb +42 -40
- data/lib/duckdb/result.rb +8 -2
- data/lib/duckdb/version.rb +1 -1
- data/sample/async_query.rb +24 -0
- data/sample/async_query_stream.rb +24 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afbb8627bfcb9764d6928d64558b55c18b26932b1ad50946cfe777169b6986f9
|
4
|
+
data.tar.gz: b560803df1d4b93d1e1b9f5c56b55f779c34095780592b9cdae51f7d4da2c0ec
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c16acf784261f874501381aa9c764bc461d56fd35b066bae88c6cf0b4de654a867a6d309641cf0cf39d60854d268ce610fd3997534adcd11f322e7e4cd76401
|
7
|
+
data.tar.gz: 24d26d68b843c27ca306980e0d1acdfed2c6f24bb573cb89ba684879c4d05d43256d2335085e82fb1c352b7cdffcd016f2c2dadf3d924fc747cc4c450b142693
|
data/.gitattributes
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
*.rb diff=ruby
|
@@ -1,9 +1,9 @@
|
|
1
1
|
name: MacOS
|
2
2
|
|
3
3
|
on:
|
4
|
-
push:
|
5
|
-
|
6
|
-
|
4
|
+
# push:
|
5
|
+
# branches:
|
6
|
+
# - main
|
7
7
|
pull_request:
|
8
8
|
types:
|
9
9
|
- opened
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: macos-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-
|
19
|
-
duckdb: ['0.9.
|
18
|
+
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-preview3', 'head']
|
19
|
+
duckdb: ['0.9.2', '0.8.1']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
@@ -59,7 +59,7 @@ jobs:
|
|
59
59
|
|
60
60
|
- name: run test with Ruby ${{ matrix.ruby }}
|
61
61
|
run: |
|
62
|
-
rake test
|
62
|
+
env RUBYOPT=-W:deprecated rake test
|
63
63
|
|
64
64
|
post-test:
|
65
65
|
name: All tests passed on macos
|
@@ -1,9 +1,9 @@
|
|
1
1
|
name: Ubuntu
|
2
2
|
|
3
3
|
on:
|
4
|
-
push:
|
5
|
-
|
6
|
-
|
4
|
+
# push:
|
5
|
+
# branches:
|
6
|
+
# - main
|
7
7
|
pull_request:
|
8
8
|
types:
|
9
9
|
- opened
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: ubuntu-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-
|
19
|
-
duckdb: ['0.9.
|
18
|
+
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-preview3', 'head']
|
19
|
+
duckdb: ['0.9.2', '0.8.1']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
@@ -57,7 +57,7 @@ jobs:
|
|
57
57
|
env:
|
58
58
|
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
59
59
|
run: |
|
60
|
-
rake test
|
60
|
+
env RUBYOPT=-W:deprecated rake test
|
61
61
|
|
62
62
|
post-test:
|
63
63
|
name: All tests passed on Ubuntu
|
@@ -1,9 +1,9 @@
|
|
1
1
|
name: Windows
|
2
2
|
|
3
3
|
on:
|
4
|
-
push:
|
5
|
-
|
6
|
-
|
4
|
+
# push:
|
5
|
+
# branches:
|
6
|
+
# - main
|
7
7
|
pull_request:
|
8
8
|
types:
|
9
9
|
- opened
|
@@ -16,7 +16,7 @@ jobs:
|
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
18
|
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', 'ucrt', 'mingw', 'mswin', 'head']
|
19
|
-
duckdb: ['0.9.
|
19
|
+
duckdb: ['0.9.2', '0.8.1']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
# 0.9.2
|
4
|
+
- add DuckDB::Connection#async_query_stream
|
5
|
+
- DuckDB::PendingResult accepts second argument. If the second argument is
|
6
|
+
true, PendingResult#execute_pending returns streaming DuckDB::Result object.
|
7
|
+
- add DuckDB::PreparedStatement#pending_prepared_stream
|
8
|
+
- add DuckDB::Result#streaming?.
|
9
|
+
|
10
|
+
# 0.9.1.2
|
11
|
+
- add DuckDB::Connection#interrupt, DuckDB::Connection#query_progress
|
12
|
+
- add DuckDB::Connection#async_query, alias method async_execute.
|
13
|
+
|
3
14
|
# 0.9.1.1
|
4
15
|
- change default branch to main from master.
|
5
16
|
- add DuckDB::PendingResult class.
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
duckdb (0.9.
|
4
|
+
duckdb (0.9.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -9,16 +9,16 @@ GEM
|
|
9
9
|
benchmark-ips (2.12.0)
|
10
10
|
mini_portile2 (2.8.5)
|
11
11
|
minitest (5.20.0)
|
12
|
-
nokogiri (1.15.
|
12
|
+
nokogiri (1.15.5)
|
13
13
|
mini_portile2 (~> 2.8.2)
|
14
14
|
racc (~> 1.4)
|
15
|
-
nokogiri (1.15.
|
15
|
+
nokogiri (1.15.5-x86_64-linux)
|
16
16
|
racc (~> 1.4)
|
17
|
-
racc (1.7.
|
17
|
+
racc (1.7.3)
|
18
18
|
rake (13.1.0)
|
19
19
|
rake-compiler (1.2.5)
|
20
20
|
rake
|
21
|
-
ruby_memcheck (2.2.
|
21
|
+
ruby_memcheck (2.2.1)
|
22
22
|
nokogiri
|
23
23
|
stackprof (0.2.25)
|
24
24
|
|
data/README.md
CHANGED
@@ -104,10 +104,25 @@ con.query('SELECT * FROM users WHERE name = ? AND email = ?', 'Alice', 'alice@ex
|
|
104
104
|
con.query('SELECT * FROM users WHERE name = $name AND email = $email', name: 'Alice', email: 'alice@example.com')
|
105
105
|
```
|
106
106
|
|
107
|
+
### using async query
|
108
|
+
|
109
|
+
You can use async query.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
DuckDB::Result.use_chunk_each = true # must be true.
|
113
|
+
...
|
114
|
+
|
115
|
+
pending_result = con.async_query_stream('SLOW QUERY')
|
116
|
+
pending_result.execute_task while pending_result.state == :not_ready
|
117
|
+
|
118
|
+
result = pending_result.execute_pending
|
119
|
+
result.each.first
|
120
|
+
```
|
121
|
+
|
122
|
+
Here is [the benchmark](./benchmark/async_query.rb).
|
107
123
|
|
108
124
|
### using BLOB column
|
109
125
|
|
110
|
-
BLOB is available with DuckDB v0.2.5 or later.
|
111
126
|
Use `DuckDB::Blob.new` or use sting#force_encoding(Encoding::BINARY)
|
112
127
|
|
113
128
|
```ruby
|
@@ -119,6 +134,7 @@ DuckDB::Database.open do |db|
|
|
119
134
|
stmt = DuckDB::PreparedStatement.new(con, 'INSERT INTO blob_table VALUES ($1)')
|
120
135
|
|
121
136
|
stmt.bind(1, DuckDB::Blob.new("\0\1\2\3\4\5"))
|
137
|
+
# or
|
122
138
|
# stmt.bind(1, "\0\1\2\3\4\5".force_encoding(Encoding::BINARY))
|
123
139
|
stmt.execute
|
124
140
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'duckdb'
|
3
|
+
require 'benchmark/ips'
|
4
|
+
|
5
|
+
|
6
|
+
DuckDB::Result.use_chunk_each = true
|
7
|
+
DuckDB::Database.open do |db|
|
8
|
+
db.connect do |con|
|
9
|
+
con.query('SET threads=1')
|
10
|
+
con.query('CREATE TABLE tbl as SELECT range a, mod(range, 10) b FROM range(100000)')
|
11
|
+
con.query('CREATE TABLE tbl2 as SELECT range a, mod(range, 10) b FROM range(100000)')
|
12
|
+
query_sql = 'SELECT * FROM tbl where b = (SELECT min(b) FROM tbl2)'
|
13
|
+
print <<~END_OF_HEAD
|
14
|
+
|
15
|
+
Benchmark: Get first record ======================================
|
16
|
+
END_OF_HEAD
|
17
|
+
|
18
|
+
Benchmark.ips do |x|
|
19
|
+
x.report('async_query') do
|
20
|
+
pending_result = con.async_query(query_sql)
|
21
|
+
|
22
|
+
pending_result.execute_task while pending_result.state == :not_ready
|
23
|
+
result = pending_result.execute_pending
|
24
|
+
result.each.first
|
25
|
+
end
|
26
|
+
x.report('query') do
|
27
|
+
result = con.query(query_sql)
|
28
|
+
result.each.first
|
29
|
+
end
|
30
|
+
x.report('async_query_stream') do
|
31
|
+
pending_result = con.async_query_stream(query_sql)
|
32
|
+
|
33
|
+
pending_result.execute_task while pending_result.state == :not_ready
|
34
|
+
result = pending_result.execute_pending
|
35
|
+
result.each.first
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
print <<~END_OF_HEAD
|
40
|
+
|
41
|
+
|
42
|
+
Benchmark: Get all records ======================================
|
43
|
+
END_OF_HEAD
|
44
|
+
|
45
|
+
Benchmark.ips do |x|
|
46
|
+
x.report('async_query') do
|
47
|
+
pending_result = con.async_query(query_sql)
|
48
|
+
|
49
|
+
pending_result.execute_task while pending_result.state == :not_ready
|
50
|
+
result = pending_result.execute_pending
|
51
|
+
result.each.to_a
|
52
|
+
end
|
53
|
+
x.report('query') do
|
54
|
+
result = con.query(query_sql)
|
55
|
+
result.each.to_a
|
56
|
+
end
|
57
|
+
x.report('async_query_stream') do
|
58
|
+
pending_result = con.async_query_stream(query_sql)
|
59
|
+
|
60
|
+
pending_result.execute_task while pending_result.state == :not_ready
|
61
|
+
result = pending_result.execute_pending
|
62
|
+
result.each.to_a
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
__END__
|
69
|
+
|
70
|
+
results:
|
71
|
+
Benchmark: Get first record ======================================
|
72
|
+
Warming up --------------------------------------
|
73
|
+
async_query 70.000 i/100ms
|
74
|
+
query 88.000 i/100ms
|
75
|
+
async_query_stream 188.000 i/100ms
|
76
|
+
Calculating -------------------------------------
|
77
|
+
async_query 847.191 (± 4.6%) i/s - 4.270k in 5.051650s
|
78
|
+
query 850.509 (± 3.8%) i/s - 4.312k in 5.078167s
|
79
|
+
async_query_stream 1.757k (± 7.3%) i/s - 8.836k in 5.057142s
|
80
|
+
|
81
|
+
|
82
|
+
Benchmark: Get all records ======================================
|
83
|
+
Warming up --------------------------------------
|
84
|
+
async_query 40.000 i/100ms
|
85
|
+
query 40.000 i/100ms
|
86
|
+
async_query_stream 39.000 i/100ms
|
87
|
+
Calculating -------------------------------------
|
88
|
+
async_query 402.567 (± 0.5%) i/s - 2.040k in 5.067639s
|
89
|
+
query 406.632 (± 0.7%) i/s - 2.040k in 5.017079s
|
90
|
+
async_query_stream 395.532 (± 0.8%) i/s - 1.989k in 5.028955s
|
data/ext/duckdb/appender.c
CHANGED
@@ -285,7 +285,7 @@ static VALUE appender__append_date(VALUE self, VALUE year, VALUE month, VALUE da
|
|
285
285
|
rubyDuckDBAppender *ctx;
|
286
286
|
|
287
287
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
288
|
-
dt =
|
288
|
+
dt = rbduckdb_to_duckdb_date_from_value(year, month, day);
|
289
289
|
|
290
290
|
if (duckdb_append_date(ctx->appender, dt) == DuckDBError) {
|
291
291
|
rb_raise(eDuckDBError, "failed to append date");
|
@@ -298,7 +298,7 @@ static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VAL
|
|
298
298
|
rubyDuckDBAppender *ctx;
|
299
299
|
|
300
300
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
301
|
-
|
301
|
+
rbduckdb_to_duckdb_interval_from_value(&interval, months, days, micros);
|
302
302
|
|
303
303
|
if (duckdb_append_interval(ctx->appender, interval) == DuckDBError) {
|
304
304
|
rb_raise(eDuckDBError, "failed to append interval");
|
@@ -311,7 +311,7 @@ static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec,
|
|
311
311
|
rubyDuckDBAppender *ctx;
|
312
312
|
|
313
313
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
314
|
-
time =
|
314
|
+
time = rbduckdb_to_duckdb_time_from_value(hour, min, sec, micros);
|
315
315
|
|
316
316
|
if (duckdb_append_time(ctx->appender, time) == DuckDBError) {
|
317
317
|
rb_raise(eDuckDBError, "failed to append time");
|
@@ -326,7 +326,7 @@ static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VAL
|
|
326
326
|
|
327
327
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
328
328
|
|
329
|
-
timestamp =
|
329
|
+
timestamp = rbduckdb_to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
|
330
330
|
|
331
331
|
if (duckdb_append_timestamp(ctx->appender, timestamp) == DuckDBError) {
|
332
332
|
rb_raise(eDuckDBError, "failed to append timestamp");
|
@@ -369,7 +369,7 @@ static VALUE appender_close(VALUE self) {
|
|
369
369
|
return self;
|
370
370
|
}
|
371
371
|
|
372
|
-
void
|
372
|
+
void rbduckdb_init_duckdb_appender(void) {
|
373
373
|
cDuckDBAppender = rb_define_class_under(mDuckDB, "Appender", rb_cObject);
|
374
374
|
rb_define_alloc_func(cDuckDBAppender, allocate);
|
375
375
|
rb_define_method(cDuckDBAppender, "initialize", appender_initialize, 3);
|
data/ext/duckdb/appender.h
CHANGED
data/ext/duckdb/blob.c
CHANGED
data/ext/duckdb/blob.h
CHANGED
data/ext/duckdb/column.c
CHANGED
@@ -68,7 +68,7 @@ VALUE duckdb_column_get_name(VALUE oDuckDBColumn) {
|
|
68
68
|
return rb_utf8_str_new_cstr(duckdb_column_name(&(ctxresult->result), ctx->col));
|
69
69
|
}
|
70
70
|
|
71
|
-
VALUE
|
71
|
+
VALUE rbduckdb_create_column(VALUE oDuckDBResult, idx_t col) {
|
72
72
|
VALUE obj;
|
73
73
|
rubyDuckDBColumn *ctx;
|
74
74
|
|
@@ -81,7 +81,7 @@ VALUE create_column(VALUE oDuckDBResult, idx_t col) {
|
|
81
81
|
return obj;
|
82
82
|
}
|
83
83
|
|
84
|
-
void
|
84
|
+
void rbduckdb_init_duckdb_column(void) {
|
85
85
|
cDuckDBColumn = rb_define_class_under(mDuckDB, "Column", rb_cObject);
|
86
86
|
rb_define_alloc_func(cDuckDBColumn, allocate);
|
87
87
|
|
data/ext/duckdb/column.h
CHANGED
@@ -8,7 +8,7 @@ struct _rubyDuckDBColumn {
|
|
8
8
|
|
9
9
|
typedef struct _rubyDuckDBColumn rubyDuckDBColumn;
|
10
10
|
|
11
|
-
void
|
12
|
-
VALUE
|
11
|
+
void rbduckdb_init_duckdb_column(void);
|
12
|
+
VALUE rbduckdb_create_column(VALUE oDuckDBResult, idx_t col);
|
13
13
|
|
14
14
|
#endif
|
data/ext/duckdb/config.c
CHANGED
@@ -79,7 +79,7 @@ static VALUE config_set_config(VALUE self, VALUE key, VALUE value) {
|
|
79
79
|
return self;
|
80
80
|
}
|
81
81
|
|
82
|
-
void
|
82
|
+
void rbduckdb_init_duckdb_config(void) {
|
83
83
|
cDuckDBConfig = rb_define_class_under(mDuckDB, "Config", rb_cObject);
|
84
84
|
rb_define_alloc_func(cDuckDBConfig, allocate);
|
85
85
|
rb_define_singleton_method(cDuckDBConfig, "size", config_s_size, 0);
|
data/ext/duckdb/config.h
CHANGED
data/ext/duckdb/connection.c
CHANGED
@@ -6,6 +6,12 @@ static void deallocate(void *ctx);
|
|
6
6
|
static VALUE allocate(VALUE klass);
|
7
7
|
static size_t memsize(const void *p);
|
8
8
|
static VALUE duckdb_connection_disconnect(VALUE self);
|
9
|
+
|
10
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
11
|
+
static VALUE duckdb_connection_interrupt(VALUE self);
|
12
|
+
static VALUE duckdb_connection_query_progress(VALUE self);
|
13
|
+
#endif
|
14
|
+
|
9
15
|
static VALUE duckdb_connection_connect(VALUE self, VALUE oDuckDBDatabase);
|
10
16
|
static VALUE duckdb_connection_query_sql(VALUE self, VALUE str);
|
11
17
|
|
@@ -37,12 +43,12 @@ rubyDuckDBConnection *get_struct_connection(VALUE obj) {
|
|
37
43
|
return ctx;
|
38
44
|
}
|
39
45
|
|
40
|
-
VALUE
|
46
|
+
VALUE rbduckdb_create_connection(VALUE oDuckDBDatabase) {
|
41
47
|
rubyDuckDB *ctxdb;
|
42
48
|
rubyDuckDBConnection *ctxcon;
|
43
49
|
VALUE obj;
|
44
50
|
|
45
|
-
ctxdb =
|
51
|
+
ctxdb = rbduckdb_get_struct_database(oDuckDBDatabase);
|
46
52
|
|
47
53
|
obj = allocate(cDuckDBConnection);
|
48
54
|
TypedData_Get_Struct(obj, rubyDuckDBConnection, &connection_data_type, ctxcon);
|
@@ -51,7 +57,6 @@ VALUE create_connection(VALUE oDuckDBDatabase) {
|
|
51
57
|
rb_raise(eDuckDBError, "connection error");
|
52
58
|
}
|
53
59
|
|
54
|
-
// rb_ivar_set(obj, rb_intern("database"), oDuckDBDatabase);
|
55
60
|
return obj;
|
56
61
|
}
|
57
62
|
|
@@ -64,6 +69,57 @@ static VALUE duckdb_connection_disconnect(VALUE self) {
|
|
64
69
|
return self;
|
65
70
|
}
|
66
71
|
|
72
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
73
|
+
/*
|
74
|
+
* call-seq:
|
75
|
+
* connection.interrupt -> nil
|
76
|
+
*
|
77
|
+
* Interrupts the currently running query.
|
78
|
+
*
|
79
|
+
* db = DuckDB::Database.open
|
80
|
+
* conn = db.connect
|
81
|
+
* con.query('SET ENABLE_PROGRESS_BAR=true')
|
82
|
+
* con.query('SET ENABLE_PROGRESS_BAR_PRINT=false')
|
83
|
+
* pending_result = con.async_query('slow query')
|
84
|
+
*
|
85
|
+
* pending_result.execute_task
|
86
|
+
* con.interrupt # => nil
|
87
|
+
*/
|
88
|
+
static VALUE duckdb_connection_interrupt(VALUE self) {
|
89
|
+
rubyDuckDBConnection *ctx;
|
90
|
+
|
91
|
+
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
92
|
+
duckdb_interrupt(ctx->con);
|
93
|
+
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
/*
|
98
|
+
* Returns the progress of the currently running query.
|
99
|
+
*
|
100
|
+
* require 'duckdb'
|
101
|
+
*
|
102
|
+
* db = DuckDB::Database.open
|
103
|
+
* conn = db.connect
|
104
|
+
* con.query('SET ENABLE_PROGRESS_BAR=true')
|
105
|
+
* con.query('SET ENABLE_PROGRESS_BAR_PRINT=false')
|
106
|
+
* con.query_progress # => -1.0
|
107
|
+
* pending_result = con.async_query('slow query')
|
108
|
+
* con.query_progress # => 0.0
|
109
|
+
* pending_result.execute_task
|
110
|
+
* con.query_progress # => Float
|
111
|
+
*/
|
112
|
+
static VALUE duckdb_connection_query_progress(VALUE self) {
|
113
|
+
rubyDuckDBConnection *ctx;
|
114
|
+
double progress;
|
115
|
+
|
116
|
+
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
117
|
+
progress = duckdb_query_progress(ctx->con);
|
118
|
+
|
119
|
+
return DBL2NUM(progress);
|
120
|
+
}
|
121
|
+
#endif
|
122
|
+
|
67
123
|
static VALUE duckdb_connection_connect(VALUE self, VALUE oDuckDBDatabase) {
|
68
124
|
rubyDuckDBConnection *ctx;
|
69
125
|
rubyDuckDB *ctxdb;
|
@@ -71,7 +127,7 @@ static VALUE duckdb_connection_connect(VALUE self, VALUE oDuckDBDatabase) {
|
|
71
127
|
if (!rb_obj_is_kind_of(oDuckDBDatabase, cDuckDBDatabase)) {
|
72
128
|
rb_raise(rb_eTypeError, "The first argument must be DuckDB::Database object.");
|
73
129
|
}
|
74
|
-
ctxdb =
|
130
|
+
ctxdb = rbduckdb_get_struct_database(oDuckDBDatabase);
|
75
131
|
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
76
132
|
|
77
133
|
if (duckdb_connect(ctxdb->db, &(ctx->con)) == DuckDBError) {
|
@@ -85,7 +141,7 @@ static VALUE duckdb_connection_query_sql(VALUE self, VALUE str) {
|
|
85
141
|
rubyDuckDBConnection *ctx;
|
86
142
|
rubyDuckDBResult *ctxr;
|
87
143
|
|
88
|
-
VALUE result =
|
144
|
+
VALUE result = rbduckdb_create_result();
|
89
145
|
|
90
146
|
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
91
147
|
ctxr = get_struct_result(result);
|
@@ -100,11 +156,15 @@ static VALUE duckdb_connection_query_sql(VALUE self, VALUE str) {
|
|
100
156
|
return result;
|
101
157
|
}
|
102
158
|
|
103
|
-
void
|
159
|
+
void rbduckdb_init_duckdb_connection(void) {
|
104
160
|
cDuckDBConnection = rb_define_class_under(mDuckDB, "Connection", rb_cObject);
|
105
161
|
rb_define_alloc_func(cDuckDBConnection, allocate);
|
106
162
|
|
107
163
|
rb_define_method(cDuckDBConnection, "disconnect", duckdb_connection_disconnect, 0);
|
164
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
165
|
+
rb_define_method(cDuckDBConnection, "interrupt", duckdb_connection_interrupt, 0);
|
166
|
+
rb_define_method(cDuckDBConnection, "query_progress", duckdb_connection_query_progress, 0);
|
167
|
+
#endif
|
108
168
|
rb_define_private_method(cDuckDBConnection, "_connect", duckdb_connection_connect, 1);
|
109
169
|
rb_define_private_method(cDuckDBConnection, "query_sql", duckdb_connection_query_sql, 1);
|
110
170
|
}
|
data/ext/duckdb/connection.h
CHANGED
@@ -8,7 +8,7 @@ struct _rubyDuckDBConnection {
|
|
8
8
|
typedef struct _rubyDuckDBConnection rubyDuckDBConnection;
|
9
9
|
|
10
10
|
rubyDuckDBConnection *get_struct_connection(VALUE obj);
|
11
|
-
void
|
12
|
-
VALUE
|
11
|
+
void rbduckdb_init_duckdb_connection(void);
|
12
|
+
VALUE rbduckdb_create_connection(VALUE oDuckDBDatabase);
|
13
13
|
|
14
14
|
#endif
|
data/ext/duckdb/converter.h
CHANGED
data/ext/duckdb/conveter.c
CHANGED
data/ext/duckdb/database.c
CHANGED
@@ -37,7 +37,7 @@ static VALUE allocate(VALUE klass) {
|
|
37
37
|
return TypedData_Wrap_Struct(klass, &database_data_type, ctx);
|
38
38
|
}
|
39
39
|
|
40
|
-
rubyDuckDB *
|
40
|
+
rubyDuckDB *rbduckdb_get_struct_database(VALUE obj) {
|
41
41
|
rubyDuckDB *ctx;
|
42
42
|
TypedData_Get_Struct(obj, rubyDuckDB, &database_data_type, ctx);
|
43
43
|
return ctx;
|
@@ -99,7 +99,7 @@ static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBData
|
|
99
99
|
}
|
100
100
|
|
101
101
|
static VALUE duckdb_database_connect(VALUE self) {
|
102
|
-
return
|
102
|
+
return rbduckdb_create_connection(self);
|
103
103
|
}
|
104
104
|
|
105
105
|
/*
|
@@ -115,7 +115,7 @@ static VALUE duckdb_database_close(VALUE self) {
|
|
115
115
|
return self;
|
116
116
|
}
|
117
117
|
|
118
|
-
void
|
118
|
+
void rbduckdb_init_duckdb_database(void) {
|
119
119
|
cDuckDBDatabase = rb_define_class_under(mDuckDB, "Database", rb_cObject);
|
120
120
|
rb_define_alloc_func(cDuckDBDatabase, allocate);
|
121
121
|
rb_define_singleton_method(cDuckDBDatabase, "_open", duckdb_database_s_open, -1);
|
data/ext/duckdb/database.h
CHANGED
data/ext/duckdb/duckdb.c
CHANGED
@@ -22,15 +22,15 @@ Init_duckdb_native(void) {
|
|
22
22
|
|
23
23
|
rb_define_singleton_method(mDuckDB, "library_version", duckdb_s_library_version, 0);
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
rbduckdb_init_duckdb_error();
|
26
|
+
rbduckdb_init_duckdb_database();
|
27
|
+
rbduckdb_init_duckdb_connection();
|
28
|
+
rbduckdb_init_duckdb_result();
|
29
|
+
rbduckdb_init_duckdb_column();
|
30
|
+
rbduckdb_init_duckdb_prepared_statement();
|
31
|
+
rbduckdb_init_duckdb_pending_result();
|
32
|
+
rbduckdb_init_duckdb_blob();
|
33
|
+
rbduckdb_init_duckdb_appender();
|
34
|
+
rbduckdb_init_duckdb_config();
|
35
|
+
rbduckdb_init_duckdb_converter();
|
36
36
|
}
|
data/ext/duckdb/error.c
CHANGED