duckdb 0.9.1.1 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
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