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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test_on_macos.yml +6 -6
  4. data/.github/workflows/test_on_ubuntu.yml +6 -6
  5. data/.github/workflows/test_on_windows.yml +4 -4
  6. data/CHANGELOG.md +11 -0
  7. data/Dockerfile +1 -1
  8. data/Gemfile.lock +5 -5
  9. data/README.md +17 -1
  10. data/benchmark/async_query.rb +90 -0
  11. data/ext/duckdb/appender.c +5 -5
  12. data/ext/duckdb/appender.h +1 -1
  13. data/ext/duckdb/blob.c +1 -1
  14. data/ext/duckdb/blob.h +1 -4
  15. data/ext/duckdb/column.c +2 -2
  16. data/ext/duckdb/column.h +2 -2
  17. data/ext/duckdb/config.c +1 -1
  18. data/ext/duckdb/config.h +1 -1
  19. data/ext/duckdb/connection.c +66 -6
  20. data/ext/duckdb/connection.h +2 -2
  21. data/ext/duckdb/converter.h +1 -1
  22. data/ext/duckdb/conveter.c +1 -1
  23. data/ext/duckdb/database.c +3 -3
  24. data/ext/duckdb/database.h +2 -2
  25. data/ext/duckdb/duckdb.c +11 -11
  26. data/ext/duckdb/error.c +1 -1
  27. data/ext/duckdb/error.h +1 -1
  28. data/ext/duckdb/extconf.rb +46 -13
  29. data/ext/duckdb/pending_result.c +45 -6
  30. data/ext/duckdb/pending_result.h +1 -1
  31. data/ext/duckdb/prepared_statement.c +7 -7
  32. data/ext/duckdb/prepared_statement.h +1 -1
  33. data/ext/duckdb/result.c +112 -70
  34. data/ext/duckdb/result.h +2 -2
  35. data/ext/duckdb/ruby-duckdb.h +1 -0
  36. data/ext/duckdb/util.c +4 -4
  37. data/ext/duckdb/util.h +4 -4
  38. data/lib/duckdb/appender.rb +1 -10
  39. data/lib/duckdb/connection.rb +50 -8
  40. data/lib/duckdb/converter.rb +27 -1
  41. data/lib/duckdb/prepared_statement.rb +42 -40
  42. data/lib/duckdb/result.rb +8 -2
  43. data/lib/duckdb/version.rb +1 -1
  44. data/sample/async_query.rb +24 -0
  45. data/sample/async_query_stream.rb +24 -0
  46. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6f3ac463fffc2fc6362c34abbfa5b862a7b8c993052ede087ca4403542c98dc8
4
- data.tar.gz: c5ea1236f240a62165b7e371ae48033447868d119261def6c5310d3911e9df91
3
+ metadata.gz: afbb8627bfcb9764d6928d64558b55c18b26932b1ad50946cfe777169b6986f9
4
+ data.tar.gz: b560803df1d4b93d1e1b9f5c56b55f779c34095780592b9cdae51f7d4da2c0ec
5
5
  SHA512:
6
- metadata.gz: 210fe783740da4b6eb7991de416a7b5581403d8ad3661625110e275c030fe9dc1192d6fe2d73dcb778e53408b0e349eb28f37f2a1308d31ff30b0b783be5e498
7
- data.tar.gz: b6fcc8d47c20ff9ce053122d9d9c03f4b19f1a72d9cd56addc1704d862ab7cfda4b3bec88bb3d8580befa006dcfeeee76138e00a2a34f065cca630bde523fb7d
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
- branches:
6
- - main
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-preview2', 'head']
19
- duckdb: ['0.9.1', '0.8.1']
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
- branches:
6
- - main
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-preview2', 'head']
19
- duckdb: ['0.9.1', '0.8.1']
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
- branches:
6
- - main
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.1', '0.8.1']
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
@@ -1,7 +1,7 @@
1
1
  ARG RUBY_VERSION=3.2.2
2
2
  FROM ruby:${RUBY_VERSION}
3
3
 
4
- ARG DUCKDB_VERSION=0.9.1
4
+ ARG DUCKDB_VERSION=0.9.2
5
5
 
6
6
  RUN apt update -qq && \
7
7
  apt install -y build-essential curl git wget
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (0.9.1.1)
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.4)
12
+ nokogiri (1.15.5)
13
13
  mini_portile2 (~> 2.8.2)
14
14
  racc (~> 1.4)
15
- nokogiri (1.15.4-x86_64-linux)
15
+ nokogiri (1.15.5-x86_64-linux)
16
16
  racc (~> 1.4)
17
- racc (1.7.1)
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.0)
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
@@ -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 = to_duckdb_date_from_value(year, month, day);
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
- to_duckdb_interval_from_value(&interval, months, days, micros);
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 = to_duckdb_time_from_value(hour, min, sec, micros);
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 = to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
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 init_duckdb_appender(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);
@@ -7,6 +7,6 @@ struct _rubyDuckDBAppender {
7
7
 
8
8
  typedef struct _rubyDuckDBAppender rubyDuckDBAppender;
9
9
 
10
- void init_duckdb_appender(void);
10
+ void rbduckdb_init_duckdb_appender(void);
11
11
 
12
12
  #endif
data/ext/duckdb/blob.c CHANGED
@@ -2,6 +2,6 @@
2
2
 
3
3
  VALUE cDuckDBBlob;
4
4
 
5
- void init_duckdb_blob(void) {
5
+ void rbduckdb_init_duckdb_blob(void) {
6
6
  cDuckDBBlob = rb_define_class_under(mDuckDB, "Blob", rb_cString);
7
7
  }
data/ext/duckdb/blob.h CHANGED
@@ -1,10 +1,7 @@
1
1
  #ifndef RUBY_DUCKDB_BLOB_H
2
2
  #define RUBY_DUCKDB_BLOB_H
3
3
 
4
- /*
5
- * blob is supported by duckdb v0.2.5 or later
6
- */
7
- void init_duckdb_blob(void);
4
+ void rbduckdb_init_duckdb_blob(void);
8
5
 
9
6
  #endif
10
7
 
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 create_column(VALUE oDuckDBResult, idx_t col) {
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 init_duckdb_column(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 init_duckdb_column(void);
12
- VALUE create_column(VALUE oDuckDBResult, idx_t col);
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 init_duckdb_config(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
@@ -9,6 +9,6 @@ typedef struct _rubyDuckDBConfig rubyDuckDBConfig;
9
9
 
10
10
  rubyDuckDBConfig *get_struct_config(VALUE obj);
11
11
 
12
- void init_duckdb_config(void);
12
+ void rbduckdb_init_duckdb_config(void);
13
13
 
14
14
  #endif
@@ -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 create_connection(VALUE oDuckDBDatabase) {
46
+ VALUE rbduckdb_create_connection(VALUE oDuckDBDatabase) {
41
47
  rubyDuckDB *ctxdb;
42
48
  rubyDuckDBConnection *ctxcon;
43
49
  VALUE obj;
44
50
 
45
- ctxdb = get_struct_database(oDuckDBDatabase);
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 = get_struct_database(oDuckDBDatabase);
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 = create_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 init_duckdb_connection(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
  }
@@ -8,7 +8,7 @@ struct _rubyDuckDBConnection {
8
8
  typedef struct _rubyDuckDBConnection rubyDuckDBConnection;
9
9
 
10
10
  rubyDuckDBConnection *get_struct_connection(VALUE obj);
11
- void init_duckdb_connection(void);
12
- VALUE create_connection(VALUE oDuckDBDatabase);
11
+ void rbduckdb_init_duckdb_connection(void);
12
+ VALUE rbduckdb_create_connection(VALUE oDuckDBDatabase);
13
13
 
14
14
  #endif
@@ -1,6 +1,6 @@
1
1
  #ifndef RUBY_DUCKDB_CONVERTER_H
2
2
  #define RUBY_DUCKDB_CONVERTER_H
3
3
 
4
- void init_duckdb_converter(void);
4
+ void rbduckdb_init_duckdb_converter(void);
5
5
 
6
6
  #endif
@@ -2,6 +2,6 @@
2
2
 
3
3
  VALUE mDuckDBConverter;
4
4
 
5
- void init_duckdb_converter(void) {
5
+ void rbduckdb_init_duckdb_converter(void) {
6
6
  mDuckDBConverter = rb_define_module_under(mDuckDB, "Converter");
7
7
  }
@@ -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 *get_struct_database(VALUE obj) {
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 create_connection(self);
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 init_duckdb_database(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);
@@ -7,7 +7,7 @@ struct _rubyDuckDB {
7
7
 
8
8
  typedef struct _rubyDuckDB rubyDuckDB;
9
9
 
10
- rubyDuckDB *get_struct_database(VALUE obj);
11
- void init_duckdb_database(void);
10
+ rubyDuckDB *rbduckdb_get_struct_database(VALUE obj);
11
+ void rbduckdb_init_duckdb_database(void);
12
12
 
13
13
  #endif
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
- init_duckdb_error();
26
- init_duckdb_database();
27
- init_duckdb_connection();
28
- init_duckdb_result();
29
- init_duckdb_column();
30
- init_duckdb_prepared_statement();
31
- init_duckdb_pending_result();
32
- init_duckdb_blob();
33
- init_duckdb_appender();
34
- init_duckdb_config();
35
- init_duckdb_converter();
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
@@ -2,6 +2,6 @@
2
2
 
3
3
  VALUE eDuckDBError;
4
4
 
5
- void init_duckdb_error(void) {
5
+ void rbduckdb_init_duckdb_error(void) {
6
6
  eDuckDBError = rb_define_class_under(mDuckDB, "Error", rb_eStandardError);
7
7
  }
data/ext/duckdb/error.h CHANGED
@@ -1,7 +1,7 @@
1
1
  #ifndef RUBY_DUCKDB_ERROR_H
2
2
  #define RUBY_DUCKDB_ERROR_H
3
3
 
4
- void init_duckdb_error(void);
4
+ void rbduckdb_init_duckdb_error(void);
5
5
 
6
6
  #endif
7
7