duckdb 0.9.2.2 → 0.10.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +27 -9
- data/Dockerfile +1 -1
- data/Gemfile.lock +9 -5
- data/README.md +28 -22
- data/benchmark/to_intern_ips.rb +73 -0
- data/duckdb.gemspec +1 -0
- data/ext/duckdb/connection.c +8 -0
- data/ext/duckdb/extconf.rb +3 -0
- data/ext/duckdb/result.c +42 -14
- data/ext/duckdb/ruby-duckdb.h +4 -0
- data/lib/duckdb/column.rb +3 -0
- data/lib/duckdb/converter.rb +14 -3
- data/lib/duckdb/result.rb +26 -13
- data/lib/duckdb/version.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e5855147af5fe02372c4bf0f67e5f5c4c046305e3d77fee7d6578d63b7d31aa7
|
4
|
+
data.tar.gz: 88701d3c0213ce6fbbe45185f82cbc823d7eb5ee6ff531ab19a720bfd72f3939
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 955bf24278d0eff8138690a9fa2dbb465c5ab94654e7be07f8001d7eeb8863af461d94c9bbdd0af4260bac0090c13bb1b18f3dd8608b55dec1d23e057577eac9
|
7
|
+
data.tar.gz: 9c2ce6b1648cd95ee16418abb01203c18f8f1d7f0360f242866c97aadd5ee1af92c1c4ba9da29146ea54904cd1acc45873ebf3cf5c0db42a6d94c4212dbeef96
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: macos-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['3.0.6', '3.1.4', '3.2.
|
19
|
-
duckdb: ['0.9.2', '0.
|
18
|
+
ruby: ['3.0.6', '3.1.4', '3.2.3', '3.3.0', 'head']
|
19
|
+
duckdb: ['0.9.2', '0.10.0']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: ubuntu-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['3.0.6', '3.1.4', '3.2.
|
19
|
-
duckdb: ['0.9.2', '0.
|
18
|
+
ruby: ['3.0.6', '3.1.4', '3.2.3', '3.3.0', 'head']
|
19
|
+
duckdb: ['0.9.2', '0.10.0']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: windows-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['3.0.6', '3.1.4', '3.2.2', 'ucrt', 'mingw', 'mswin', 'head']
|
19
|
-
duckdb: ['0.9.2', '0.
|
18
|
+
ruby: ['3.0.6', '3.1.4', '3.2.2', '3.3.0', 'ucrt', 'mingw', 'mswin', 'head']
|
19
|
+
duckdb: ['0.9.2', '0.10.0']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
data/CHANGELOG.md
CHANGED
@@ -1,27 +1,45 @@
|
|
1
|
-
#
|
1
|
+
# Changelog
|
2
2
|
|
3
|
-
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
|
5
|
+
## Unreleased
|
6
|
+
|
7
|
+
# 0.10.0.0 - 2024-02-18
|
8
|
+
- bump to duckdb 0.10.0.
|
9
|
+
- fix building error with duckdb v0.10.0.
|
10
|
+
- bundle update to bump nokogiri from 1.16.0 to 1.16.2.
|
11
|
+
- fix Decimal type conversion.
|
12
|
+
|
13
|
+
## Breaking changes
|
14
|
+
|
15
|
+
- `DuckDB::Connection#query_progress` returns `DuckDB::QueryProgress` object only when duckdb library version is 0.10.0.
|
16
|
+
- The available methods are `DuckDB::QueryProgress#percentage`, `DuckDB::QueryProgress#rows_processed`, `DuckDB::QueryProgress#total_rows_to_process`.
|
17
|
+
|
18
|
+
# 0.9.2.3 - 2023-12-29
|
19
|
+
- fix bigdecimal warning with Ruby 3.3.0.
|
20
|
+
|
21
|
+
# 0.9.2.2 - 2023-12-26
|
4
22
|
- bump Ruby to 3.3.0 on CI.
|
5
23
|
|
6
24
|
## Breaking changes
|
7
25
|
- drop Ruby 2.7.
|
8
26
|
|
9
|
-
# 0.9.2.1
|
27
|
+
# 0.9.2.1 - 2023-12-24
|
10
28
|
- support Time column in `DuckDB#Result#chunk_each`.
|
11
29
|
- add `DuckDB::Interval#eql?`.
|
12
30
|
|
13
|
-
# 0.9.2
|
31
|
+
# 0.9.2 - 2023-11-26
|
14
32
|
- add `DuckDB::Connection#async_query_stream`.
|
15
33
|
- `DuckDB::PendingResult` accepts second argument. If the second argument is
|
16
34
|
true, `PendingResult#execute_pending` returns streaming `DuckDB::Result` object.
|
17
35
|
- add `DuckDB::PreparedStatement#pending_prepared_stream`
|
18
36
|
- add `DuckDB::Result#streaming?`.
|
19
37
|
|
20
|
-
# 0.9.1.2
|
38
|
+
# 0.9.1.2 - 2023-11-05
|
21
39
|
- add `DuckDB::Connection#interrupt`, `DuckDB::Connection#query_progress`.
|
22
40
|
- add `DuckDB::Connection#async_query`, alias method `async_execute`.
|
23
41
|
|
24
|
-
# 0.9.1.1
|
42
|
+
# 0.9.1.1 - 2023-10-29
|
25
43
|
- change default branch to main from master.
|
26
44
|
- add `DuckDB::PendingResult` class.
|
27
45
|
- add `DuckDB::PendingResult#state`.
|
@@ -32,15 +50,15 @@
|
|
32
50
|
## Breaking Changes
|
33
51
|
- drop duckdb v0.7.x.
|
34
52
|
|
35
|
-
# 0.9.1
|
53
|
+
# 0.9.1 - 2023-10-14
|
36
54
|
- add `DuckDB::PreparedStatement#parameter_name`.
|
37
55
|
- bump duckdb to 0.9.1.
|
38
56
|
|
39
|
-
# 0.9.0.1
|
57
|
+
# 0.9.0.1 - 2023-10-08
|
40
58
|
- add `DuckDB::PreparedStatement#bind_parameter_index`.
|
41
59
|
- `DuckDB::Connection#query` accepts SQL with named bind parameters.
|
42
60
|
|
43
|
-
# 0.9.0
|
61
|
+
# 0.9.0 - 2023-09-30
|
44
62
|
- bump duckdb to 0.9.0.
|
45
63
|
|
46
64
|
## Breaking Changes
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,24 +1,28 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
duckdb (0.
|
4
|
+
duckdb (0.10.0.0)
|
5
|
+
bigdecimal (>= 3.1.4)
|
5
6
|
|
6
7
|
GEM
|
7
8
|
remote: https://rubygems.org/
|
8
9
|
specs:
|
9
10
|
benchmark-ips (2.13.0)
|
11
|
+
bigdecimal (3.1.6)
|
10
12
|
mini_portile2 (2.8.5)
|
11
|
-
minitest (5.
|
12
|
-
nokogiri (1.
|
13
|
+
minitest (5.22.2)
|
14
|
+
nokogiri (1.16.2)
|
13
15
|
mini_portile2 (~> 2.8.2)
|
14
16
|
racc (~> 1.4)
|
17
|
+
nokogiri (1.16.2-x86_64-linux)
|
18
|
+
racc (~> 1.4)
|
15
19
|
racc (1.7.3)
|
16
20
|
rake (13.1.0)
|
17
|
-
rake-compiler (1.2.
|
21
|
+
rake-compiler (1.2.7)
|
18
22
|
rake
|
19
23
|
ruby_memcheck (2.3.0)
|
20
24
|
nokogiri
|
21
|
-
stackprof (0.2.
|
25
|
+
stackprof (0.2.26)
|
22
26
|
|
23
27
|
PLATFORMS
|
24
28
|
ruby
|
data/README.md
CHANGED
@@ -7,32 +7,34 @@
|
|
7
7
|
|
8
8
|
## Description
|
9
9
|
|
10
|
-
|
10
|
+
This gem `duckdb` is Ruby client for the [DuckDB](https://www.duckdb.org) database engine.
|
11
11
|
|
12
12
|
## Requirement
|
13
13
|
|
14
|
-
You must have [DuckDB](
|
14
|
+
You must have [DuckDB](https://www.duckdb.org) engine installed in order to use this gem.
|
15
15
|
|
16
16
|
## Pre-requisite setup (Linux):
|
17
|
-
1. Head over to the [DuckDB](https://duckdb.org/) webpage
|
17
|
+
1. Head over to the [DuckDB](https://duckdb.org/) webpage.
|
18
18
|
|
19
|
-
2. Download the latest C++ package release for DuckDB
|
19
|
+
2. Download the latest C++ package release for DuckDB.
|
20
20
|
|
21
21
|
3. Move the files to their respective location:
|
22
|
-
- Extract the `duckdb.h` and `duckdb.hpp` file to `/usr/local/include
|
23
|
-
- Extract the `libduckdb.so` file to `/usr/local/lib
|
22
|
+
- Extract the `duckdb.h` and `duckdb.hpp` file to `/usr/local/include`.
|
23
|
+
- Extract the `libduckdb.so` file to `/usr/local/lib`.
|
24
24
|
|
25
25
|
```sh
|
26
26
|
unzip libduckdb-linux-amd64.zip -d libduckdb
|
27
27
|
sudo mv libduckdb/duckdb.* /usr/local/include/
|
28
28
|
sudo mv libduckdb/libduckdb.so /usr/local/lib
|
29
29
|
```
|
30
|
+
|
30
31
|
4. To create the necessary link, run `ldconfig` as root:
|
31
32
|
|
32
33
|
```sh
|
33
34
|
sudo ldconfig /usr/local/lib # adding a --verbose flag is optional - but this will let you know if the libduckdb.so library has been linked
|
34
35
|
```
|
35
|
-
|
36
|
+
|
37
|
+
## Pre-requisite setup (macOS):
|
36
38
|
|
37
39
|
Using `brew install` is recommended.
|
38
40
|
|
@@ -40,14 +42,15 @@ Using `brew install` is recommended.
|
|
40
42
|
brew install duckdb
|
41
43
|
```
|
42
44
|
|
43
|
-
## How to
|
45
|
+
## How to install
|
44
46
|
|
45
47
|
```sh
|
46
48
|
gem install duckdb
|
47
49
|
```
|
48
|
-
> this will work fine with the above pre-requisite setup.
|
49
50
|
|
50
|
-
|
51
|
+
After you've run the above pre-requisite setup, this should work fine.
|
52
|
+
|
53
|
+
If it doesn't, you may habe to specify the location of the C header and library files:
|
51
54
|
|
52
55
|
```sh
|
53
56
|
gem install duckdb -- --with-duckdb-include=/duckdb_header_directory --with-duckdb-lib=/duckdb_library_directory
|
@@ -69,7 +72,7 @@ con.query("INSERT into users VALUES(3, 'Cathy')")
|
|
69
72
|
|
70
73
|
result = con.query('SELECT * from users')
|
71
74
|
result.each do |row|
|
72
|
-
|
75
|
+
puts row
|
73
76
|
end
|
74
77
|
```
|
75
78
|
|
@@ -88,13 +91,13 @@ DuckDB::Database.open do |db|
|
|
88
91
|
|
89
92
|
result = con.query('SELECT * from users')
|
90
93
|
result.each do |row|
|
91
|
-
|
94
|
+
puts row
|
92
95
|
end
|
93
96
|
end
|
94
97
|
end
|
95
98
|
```
|
96
99
|
|
97
|
-
###
|
100
|
+
### Using bind variables
|
98
101
|
|
99
102
|
You can use bind variables.
|
100
103
|
|
@@ -104,12 +107,12 @@ con.query('SELECT * FROM users WHERE name = ? AND email = ?', 'Alice', 'alice@ex
|
|
104
107
|
con.query('SELECT * FROM users WHERE name = $name AND email = $email', name: 'Alice', email: 'alice@example.com')
|
105
108
|
```
|
106
109
|
|
107
|
-
###
|
110
|
+
### Using async query
|
108
111
|
|
109
112
|
You can use async query.
|
110
113
|
|
111
114
|
```ruby
|
112
|
-
DuckDB::Result.use_chunk_each = true
|
115
|
+
DuckDB::Result.use_chunk_each = true
|
113
116
|
...
|
114
117
|
|
115
118
|
pending_result = con.async_query_stream('SLOW QUERY')
|
@@ -121,9 +124,9 @@ result.each.first
|
|
121
124
|
|
122
125
|
Here is [the benchmark](./benchmark/async_query.rb).
|
123
126
|
|
124
|
-
###
|
127
|
+
### Using BLOB column
|
125
128
|
|
126
|
-
Use `DuckDB::Blob.new` or use
|
129
|
+
Use `DuckDB::Blob.new` or use string#force_encoding(Encoding::BINARY)
|
127
130
|
|
128
131
|
```ruby
|
129
132
|
require 'duckdb'
|
@@ -134,12 +137,12 @@ DuckDB::Database.open do |db|
|
|
134
137
|
stmt = DuckDB::PreparedStatement.new(con, 'INSERT INTO blob_table VALUES ($1)')
|
135
138
|
|
136
139
|
stmt.bind(1, DuckDB::Blob.new("\0\1\2\3\4\5"))
|
137
|
-
#
|
140
|
+
# or
|
138
141
|
# stmt.bind(1, "\0\1\2\3\4\5".force_encoding(Encoding::BINARY))
|
139
142
|
stmt.execute
|
140
143
|
|
141
144
|
result = con.query('SELECT binary_data FROM blob_table')
|
142
|
-
|
145
|
+
puts result.first.first
|
143
146
|
end
|
144
147
|
end
|
145
148
|
```
|
@@ -212,14 +215,17 @@ Config class provides Ruby interface of [DuckDB configuration](https://duckdb.or
|
|
212
215
|
|
213
216
|
```ruby
|
214
217
|
require 'duckdb'
|
218
|
+
|
215
219
|
config = DuckDB::Config.new
|
216
220
|
config['default_order'] = 'DESC'
|
221
|
+
|
217
222
|
db = DuckDB::Database.open(nil, config)
|
223
|
+
|
218
224
|
con = db.connect
|
219
225
|
con.query('CREATE TABLE numbers (number INTEGER)')
|
220
226
|
con.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')
|
221
227
|
|
222
|
-
# number is ordered by descending
|
223
|
-
|
224
|
-
|
228
|
+
# number is ordered by descending
|
229
|
+
res = con.query('SELECT number FROM numbers ORDER BY number')
|
230
|
+
res.first.first # => 4
|
225
231
|
```
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'duckdb'
|
5
|
+
require 'benchmark/ips'
|
6
|
+
|
7
|
+
DuckDB::Result.use_chunk_each = true
|
8
|
+
db = DuckDB::Database.open
|
9
|
+
con = db.connect
|
10
|
+
con.query(<<~SQL
|
11
|
+
CREATE TABLE t (
|
12
|
+
date_value DATE,
|
13
|
+
time_value TIME,
|
14
|
+
timestamp_value TIMESTAMP,
|
15
|
+
interval_value INTERVAL,
|
16
|
+
hugeint_value HUGEINT,
|
17
|
+
uuid_value UUID,
|
18
|
+
decimal_value DECIMAL(4, 2)
|
19
|
+
)
|
20
|
+
SQL
|
21
|
+
)
|
22
|
+
con.query(<<~SQL
|
23
|
+
INSERT INTO t VALUES
|
24
|
+
(
|
25
|
+
'2019-01-01',
|
26
|
+
'12:00:00',
|
27
|
+
'2019-01-01 12:00:00',
|
28
|
+
'1 day',
|
29
|
+
12345678901234567890,
|
30
|
+
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
31
|
+
0.12
|
32
|
+
),
|
33
|
+
(
|
34
|
+
'2019-01-01',
|
35
|
+
'12:00:00',
|
36
|
+
'2019-01-01 12:00:00',
|
37
|
+
'1 day',
|
38
|
+
12345678901234567890,
|
39
|
+
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
40
|
+
0.12
|
41
|
+
),
|
42
|
+
(
|
43
|
+
'2019-01-01',
|
44
|
+
'12:00:00',
|
45
|
+
'2019-01-01 12:00:00',
|
46
|
+
'1 day',
|
47
|
+
12345678901234567890,
|
48
|
+
'a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11',
|
49
|
+
2.12
|
50
|
+
)
|
51
|
+
SQL
|
52
|
+
)
|
53
|
+
result = con.query('SELECT * FROM t')
|
54
|
+
|
55
|
+
Benchmark.ips do |x|
|
56
|
+
x.report('_to_date') { result.each.to_a }
|
57
|
+
end
|
58
|
+
|
59
|
+
__END__
|
60
|
+
```
|
61
|
+
## before
|
62
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]
|
63
|
+
Warming up --------------------------------------
|
64
|
+
_to_date 30.790k i/100ms
|
65
|
+
Calculating -------------------------------------
|
66
|
+
_to_date 365.254k (± 0.2%) i/s - 1.847M in 5.057875s
|
67
|
+
|
68
|
+
## after
|
69
|
+
ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x86_64-linux]
|
70
|
+
Warming up --------------------------------------
|
71
|
+
_to_date 36.047k i/100ms
|
72
|
+
Calculating -------------------------------------
|
73
|
+
_to_date 383.760k (± 3.3%) i/s - 1.947M in 5.077849s
|
data/duckdb.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.require_paths = ['lib']
|
28
28
|
spec.extensions = ['ext/duckdb/extconf.rb']
|
29
29
|
spec.required_ruby_version = '>= 3.0.0'
|
30
|
+
spec.add_dependency 'bigdecimal', '>= 3.1.4'
|
30
31
|
|
31
32
|
spec.add_development_dependency 'bundler', '~> 2.3'
|
32
33
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
data/ext/duckdb/connection.c
CHANGED
@@ -111,12 +111,20 @@ static VALUE duckdb_connection_interrupt(VALUE self) {
|
|
111
111
|
*/
|
112
112
|
static VALUE duckdb_connection_query_progress(VALUE self) {
|
113
113
|
rubyDuckDBConnection *ctx;
|
114
|
+
#ifdef HAVE_DUCKDB_H_GE_V0_10_0
|
115
|
+
duckdb_query_progress_type progress;
|
116
|
+
#else
|
114
117
|
double progress;
|
118
|
+
#endif
|
115
119
|
|
116
120
|
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
117
121
|
progress = duckdb_query_progress(ctx->con);
|
118
122
|
|
123
|
+
#ifdef HAVE_DUCKDB_H_GE_V0_10_0
|
124
|
+
return rb_funcall(mDuckDBConverter, rb_intern("_to_query_progress"), 3, DBL2NUM(progress.percentage), ULL2NUM(progress.rows_processed), ULL2NUM(progress.total_rows_to_process));
|
125
|
+
#else
|
119
126
|
return DBL2NUM(progress);
|
127
|
+
#endif
|
120
128
|
}
|
121
129
|
#endif
|
122
130
|
|
data/ext/duckdb/extconf.rb
CHANGED
@@ -58,6 +58,9 @@ check_duckdb_library('duckdb', 'duckdb_string_is_inlined', DUCKDB_REQUIRED_VERSI
|
|
58
58
|
# check duckdb >= 0.9.0
|
59
59
|
have_func('duckdb_bind_parameter_index', 'duckdb.h')
|
60
60
|
|
61
|
+
# check duckdb >= 0.10.0
|
62
|
+
have_func('duckdb_appender_column_count', 'duckdb.h')
|
63
|
+
|
61
64
|
# duckdb_parameter_name is not found on Windows.
|
62
65
|
have_func('duckdb_parameter_name', 'duckdb.h')
|
63
66
|
|
data/ext/duckdb/result.c
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
#include "ruby-duckdb.h"
|
2
2
|
|
3
3
|
static VALUE cDuckDBResult;
|
4
|
+
static ID id__to_date;
|
5
|
+
static ID id__to_time;
|
6
|
+
static ID id__to_time_from_duckdb_time;
|
7
|
+
static ID id__to_interval_from_vector;
|
8
|
+
static ID id__to_hugeint_from_vector;
|
9
|
+
static ID id__to_decimal_from_hugeint;
|
10
|
+
static ID id__to_uuid_from_vector;
|
4
11
|
|
5
12
|
static void deallocate(void *ctx);
|
6
13
|
static VALUE allocate(VALUE klass);
|
@@ -482,7 +489,7 @@ VALUE rbduckdb_create_result(void) {
|
|
482
489
|
static VALUE vector_date(void *vector_data, idx_t row_idx) {
|
483
490
|
duckdb_date_struct date = duckdb_from_date(((duckdb_date *) vector_data)[row_idx]);
|
484
491
|
|
485
|
-
return rb_funcall(mDuckDBConverter,
|
492
|
+
return rb_funcall(mDuckDBConverter, id__to_date, 3,
|
486
493
|
INT2FIX(date.year),
|
487
494
|
INT2FIX(date.month),
|
488
495
|
INT2FIX(date.day)
|
@@ -491,7 +498,7 @@ static VALUE vector_date(void *vector_data, idx_t row_idx) {
|
|
491
498
|
|
492
499
|
static VALUE vector_timestamp(void* vector_data, idx_t row_idx) {
|
493
500
|
duckdb_timestamp_struct data = duckdb_from_timestamp(((duckdb_timestamp *)vector_data)[row_idx]);
|
494
|
-
return rb_funcall(mDuckDBConverter,
|
501
|
+
return rb_funcall(mDuckDBConverter, id__to_time, 7,
|
495
502
|
INT2FIX(data.date.year),
|
496
503
|
INT2FIX(data.date.month),
|
497
504
|
INT2FIX(data.date.day),
|
@@ -504,7 +511,7 @@ static VALUE vector_timestamp(void* vector_data, idx_t row_idx) {
|
|
504
511
|
|
505
512
|
static VALUE vector_time(void* vector_data, idx_t row_idx) {
|
506
513
|
duckdb_time_struct data = duckdb_from_time(((duckdb_time *)vector_data)[row_idx]);
|
507
|
-
return rb_funcall(mDuckDBConverter,
|
514
|
+
return rb_funcall(mDuckDBConverter, id__to_time_from_duckdb_time, 4,
|
508
515
|
INT2FIX(data.hour),
|
509
516
|
INT2FIX(data.min),
|
510
517
|
INT2FIX(data.sec),
|
@@ -515,7 +522,7 @@ static VALUE vector_time(void* vector_data, idx_t row_idx) {
|
|
515
522
|
|
516
523
|
static VALUE vector_interval(void* vector_data, idx_t row_idx) {
|
517
524
|
duckdb_interval data = ((duckdb_interval *)vector_data)[row_idx];
|
518
|
-
return rb_funcall(mDuckDBConverter,
|
525
|
+
return rb_funcall(mDuckDBConverter, id__to_interval_from_vector, 3,
|
519
526
|
INT2NUM(data.months),
|
520
527
|
INT2NUM(data.days),
|
521
528
|
LL2NUM(data.micros)
|
@@ -542,34 +549,47 @@ static VALUE vector_varchar(void* vector_data, idx_t row_idx) {
|
|
542
549
|
|
543
550
|
static VALUE vector_hugeint(void* vector_data, idx_t row_idx) {
|
544
551
|
duckdb_hugeint hugeint = ((duckdb_hugeint *)vector_data)[row_idx];
|
545
|
-
return rb_funcall(mDuckDBConverter,
|
552
|
+
return rb_funcall(mDuckDBConverter, id__to_hugeint_from_vector, 2,
|
546
553
|
ULL2NUM(hugeint.lower),
|
547
554
|
LL2NUM(hugeint.upper)
|
548
555
|
);
|
549
556
|
}
|
550
557
|
|
551
558
|
static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row_idx) {
|
552
|
-
|
553
|
-
|
559
|
+
VALUE width = INT2FIX(duckdb_decimal_width(ty));
|
560
|
+
VALUE scale = INT2FIX(duckdb_decimal_scale(ty));
|
554
561
|
duckdb_type type = duckdb_decimal_internal_type(ty);
|
555
562
|
duckdb_hugeint value;
|
563
|
+
VALUE upper = Qnil;
|
564
|
+
VALUE lower = Qnil;
|
556
565
|
|
557
566
|
value.upper = 0;
|
558
567
|
value.lower = 0;
|
559
568
|
|
560
|
-
switch(
|
569
|
+
switch(type) {
|
561
570
|
case DUCKDB_TYPE_HUGEINT:
|
562
571
|
value = ((duckdb_hugeint *) vector_data)[row_idx];
|
572
|
+
upper = LL2NUM(value.upper);
|
573
|
+
lower = ULL2NUM(value.lower);
|
574
|
+
break;
|
575
|
+
case DUCKDB_TYPE_SMALLINT:
|
576
|
+
upper = INT2FIX(((int16_t *) vector_data)[row_idx]);
|
577
|
+
break;
|
578
|
+
case DUCKDB_TYPE_INTEGER:
|
579
|
+
upper = INT2NUM(((int32_t *) vector_data)[row_idx]);
|
580
|
+
break;
|
581
|
+
case DUCKDB_TYPE_BIGINT:
|
582
|
+
upper = LL2NUM(((int64_t *) vector_data)[row_idx]);
|
563
583
|
break;
|
564
584
|
default:
|
565
585
|
rb_warn("Unknown decimal internal type %d", type);
|
566
586
|
}
|
567
587
|
|
568
|
-
return rb_funcall(mDuckDBConverter,
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
588
|
+
return rb_funcall(mDuckDBConverter, id__to_decimal_from_hugeint, 4,
|
589
|
+
width,
|
590
|
+
scale,
|
591
|
+
upper,
|
592
|
+
lower
|
573
593
|
);
|
574
594
|
}
|
575
595
|
|
@@ -665,7 +685,7 @@ static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t r
|
|
665
685
|
|
666
686
|
static VALUE vector_uuid(void* vector_data, idx_t row_idx) {
|
667
687
|
duckdb_hugeint hugeint = ((duckdb_hugeint *)vector_data)[row_idx];
|
668
|
-
return rb_funcall(mDuckDBConverter,
|
688
|
+
return rb_funcall(mDuckDBConverter, id__to_uuid_from_vector, 2,
|
669
689
|
ULL2NUM(hugeint.lower),
|
670
690
|
LL2NUM(hugeint.upper)
|
671
691
|
);
|
@@ -774,6 +794,14 @@ static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
|
|
774
794
|
|
775
795
|
void rbduckdb_init_duckdb_result(void) {
|
776
796
|
cDuckDBResult = rb_define_class_under(mDuckDB, "Result", rb_cObject);
|
797
|
+
id__to_date = rb_intern("_to_date");
|
798
|
+
id__to_time = rb_intern("_to_time");
|
799
|
+
id__to_time_from_duckdb_time = rb_intern("_to_time_from_duckdb_time");
|
800
|
+
id__to_interval_from_vector = rb_intern("_to_interval_from_vector");
|
801
|
+
id__to_hugeint_from_vector = rb_intern("_to_hugeint_from_vector");
|
802
|
+
id__to_decimal_from_hugeint = rb_intern("_to_decimal_from_hugeint");
|
803
|
+
id__to_uuid_from_vector = rb_intern("_to_uuid_from_vector");
|
804
|
+
|
777
805
|
rb_define_alloc_func(cDuckDBResult, allocate);
|
778
806
|
|
779
807
|
rb_define_method(cDuckDBResult, "column_count", duckdb_result_column_count, 0);
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
data/lib/duckdb/column.rb
CHANGED
data/lib/duckdb/converter.rb
CHANGED
@@ -4,6 +4,8 @@ require 'date'
|
|
4
4
|
require_relative 'interval'
|
5
5
|
|
6
6
|
module DuckDB
|
7
|
+
QueryProgress = Struct.new(:percentage, :rows_processed, :total_rows_to_process)
|
8
|
+
|
7
9
|
module Converter
|
8
10
|
HALF_HUGEINT_BIT = 64
|
9
11
|
HALF_HUGEINT = 1 << HALF_HUGEINT_BIT
|
@@ -35,10 +37,15 @@ module DuckDB
|
|
35
37
|
(upper << HALF_HUGEINT_BIT) + lower
|
36
38
|
end
|
37
39
|
|
38
|
-
def
|
39
|
-
v = _to_hugeint_from_vector(lower, upper)
|
40
|
+
def _to_decimal_from_hugeint(width, scale, upper, lower = nil)
|
41
|
+
v = lower.nil? ? upper : _to_hugeint_from_vector(lower, upper)
|
42
|
+
_to_decimal_from_value(width, scale, v)
|
43
|
+
end
|
44
|
+
|
45
|
+
def _to_decimal_from_value(_width, scale, value)
|
46
|
+
v = value.to_s
|
40
47
|
v = v.rjust(scale + 1, '0') if v.length < scale
|
41
|
-
v[-scale, 0] = '.'
|
48
|
+
v[-scale, 0] = '.' if scale.positive?
|
42
49
|
BigDecimal(v)
|
43
50
|
end
|
44
51
|
|
@@ -80,6 +87,10 @@ module DuckDB
|
|
80
87
|
end
|
81
88
|
end
|
82
89
|
|
90
|
+
def _to_query_progress(percentage, rows_processed, total_rows_to_process)
|
91
|
+
DuckDB::QueryProgress.new(percentage, rows_processed, total_rows_to_process).freeze
|
92
|
+
end
|
93
|
+
|
83
94
|
private
|
84
95
|
|
85
96
|
def integer_to_hugeint(value)
|
data/lib/duckdb/result.rb
CHANGED
@@ -24,18 +24,31 @@ module DuckDB
|
|
24
24
|
# end
|
25
25
|
class Result
|
26
26
|
include Enumerable
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
27
|
+
TO_METHODS = if Gem::Version.new(DuckDB::LIBRARY_VERSION) >= Gem::Version.new('0.10.0')
|
28
|
+
Hash.new(:_to_string).merge(
|
29
|
+
1 => :_to_boolean,
|
30
|
+
3 => :_to_smallint,
|
31
|
+
4 => :_to_integer,
|
32
|
+
5 => :_to_bigint,
|
33
|
+
10 => :_to_float,
|
34
|
+
11 => :_to_double,
|
35
|
+
16 => :_to_hugeint_internal,
|
36
|
+
19 => :_to_blob,
|
37
|
+
20 => :_to_decimal_internal
|
38
|
+
).freeze
|
39
|
+
else
|
40
|
+
Hash.new(:_to_string).merge(
|
41
|
+
1 => :_to_boolean,
|
42
|
+
3 => :_to_smallint,
|
43
|
+
4 => :_to_integer,
|
44
|
+
5 => :_to_bigint,
|
45
|
+
10 => :_to_float,
|
46
|
+
11 => :_to_double,
|
47
|
+
16 => :_to_hugeint_internal,
|
48
|
+
18 => :_to_blob,
|
49
|
+
19 => :_to_decimal_internal
|
50
|
+
).freeze
|
51
|
+
end
|
39
52
|
|
40
53
|
alias column_size column_count
|
41
54
|
alias row_size row_count
|
@@ -114,7 +127,7 @@ module DuckDB
|
|
114
127
|
|
115
128
|
def _to_decimal_internal(row, col)
|
116
129
|
lower, upper, width, scale = __to_decimal_internal(row, col)
|
117
|
-
Converter.
|
130
|
+
Converter._to_decimal_from_hugeint(width, scale, upper, lower)
|
118
131
|
end
|
119
132
|
end
|
120
133
|
end
|
data/lib/duckdb/version.rb
CHANGED
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duckdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.10.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masaki Suketa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-02-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bigdecimal
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 3.1.4
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.1.4
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -95,6 +109,7 @@ files:
|
|
95
109
|
- benchmark/to_bigdecimal_ips.rb
|
96
110
|
- benchmark/to_hugeint_ips.rb
|
97
111
|
- benchmark/to_hugeint_profile.rb
|
112
|
+
- benchmark/to_intern_ips.rb
|
98
113
|
- bin/console
|
99
114
|
- bin/setup
|
100
115
|
- docker-compose.yml
|