duckdb 0.9.2.3 → 0.10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +2 -2
- data/.github/workflows/test_on_ubuntu.yml +2 -2
- data/.github/workflows/test_on_windows.yml +2 -2
- data/CHANGELOG.md +25 -10
- data/Dockerfile +1 -1
- data/Gemfile.lock +7 -7
- data/README.md +28 -22
- data/benchmark/to_intern_ips.rb +73 -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 +3 -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,30 +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
|
|
4
19
|
- fix bigdecimal warning with Ruby 3.3.0.
|
|
5
20
|
|
|
6
|
-
# 0.9.2.2
|
|
21
|
+
# 0.9.2.2 - 2023-12-26
|
|
7
22
|
- bump Ruby to 3.3.0 on CI.
|
|
8
23
|
|
|
9
24
|
## Breaking changes
|
|
10
25
|
- drop Ruby 2.7.
|
|
11
26
|
|
|
12
|
-
# 0.9.2.1
|
|
27
|
+
# 0.9.2.1 - 2023-12-24
|
|
13
28
|
- support Time column in `DuckDB#Result#chunk_each`.
|
|
14
29
|
- add `DuckDB::Interval#eql?`.
|
|
15
30
|
|
|
16
|
-
# 0.9.2
|
|
31
|
+
# 0.9.2 - 2023-11-26
|
|
17
32
|
- add `DuckDB::Connection#async_query_stream`.
|
|
18
33
|
- `DuckDB::PendingResult` accepts second argument. If the second argument is
|
|
19
34
|
true, `PendingResult#execute_pending` returns streaming `DuckDB::Result` object.
|
|
20
35
|
- add `DuckDB::PreparedStatement#pending_prepared_stream`
|
|
21
36
|
- add `DuckDB::Result#streaming?`.
|
|
22
37
|
|
|
23
|
-
# 0.9.1.2
|
|
38
|
+
# 0.9.1.2 - 2023-11-05
|
|
24
39
|
- add `DuckDB::Connection#interrupt`, `DuckDB::Connection#query_progress`.
|
|
25
40
|
- add `DuckDB::Connection#async_query`, alias method `async_execute`.
|
|
26
41
|
|
|
27
|
-
# 0.9.1.1
|
|
42
|
+
# 0.9.1.1 - 2023-10-29
|
|
28
43
|
- change default branch to main from master.
|
|
29
44
|
- add `DuckDB::PendingResult` class.
|
|
30
45
|
- add `DuckDB::PendingResult#state`.
|
|
@@ -35,15 +50,15 @@
|
|
|
35
50
|
## Breaking Changes
|
|
36
51
|
- drop duckdb v0.7.x.
|
|
37
52
|
|
|
38
|
-
# 0.9.1
|
|
53
|
+
# 0.9.1 - 2023-10-14
|
|
39
54
|
- add `DuckDB::PreparedStatement#parameter_name`.
|
|
40
55
|
- bump duckdb to 0.9.1.
|
|
41
56
|
|
|
42
|
-
# 0.9.0.1
|
|
57
|
+
# 0.9.0.1 - 2023-10-08
|
|
43
58
|
- add `DuckDB::PreparedStatement#bind_parameter_index`.
|
|
44
59
|
- `DuckDB::Connection#query` accepts SQL with named bind parameters.
|
|
45
60
|
|
|
46
|
-
# 0.9.0
|
|
61
|
+
# 0.9.0 - 2023-09-30
|
|
47
62
|
- bump duckdb to 0.9.0.
|
|
48
63
|
|
|
49
64
|
## Breaking Changes
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
duckdb (0.
|
|
4
|
+
duckdb (0.10.0.0)
|
|
5
5
|
bigdecimal (>= 3.1.4)
|
|
6
6
|
|
|
7
7
|
GEM
|
|
8
8
|
remote: https://rubygems.org/
|
|
9
9
|
specs:
|
|
10
10
|
benchmark-ips (2.13.0)
|
|
11
|
-
bigdecimal (3.1.
|
|
11
|
+
bigdecimal (3.1.6)
|
|
12
12
|
mini_portile2 (2.8.5)
|
|
13
|
-
minitest (5.
|
|
14
|
-
nokogiri (1.16.
|
|
13
|
+
minitest (5.22.2)
|
|
14
|
+
nokogiri (1.16.2)
|
|
15
15
|
mini_portile2 (~> 2.8.2)
|
|
16
16
|
racc (~> 1.4)
|
|
17
|
-
nokogiri (1.16.
|
|
17
|
+
nokogiri (1.16.2-x86_64-linux)
|
|
18
18
|
racc (~> 1.4)
|
|
19
19
|
racc (1.7.3)
|
|
20
20
|
rake (13.1.0)
|
|
21
|
-
rake-compiler (1.2.
|
|
21
|
+
rake-compiler (1.2.7)
|
|
22
22
|
rake
|
|
23
23
|
ruby_memcheck (2.3.0)
|
|
24
24
|
nokogiri
|
|
25
|
-
stackprof (0.2.
|
|
25
|
+
stackprof (0.2.26)
|
|
26
26
|
|
|
27
27
|
PLATFORMS
|
|
28
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/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,14 +1,14 @@
|
|
|
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
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bigdecimal
|
|
@@ -109,6 +109,7 @@ files:
|
|
|
109
109
|
- benchmark/to_bigdecimal_ips.rb
|
|
110
110
|
- benchmark/to_hugeint_ips.rb
|
|
111
111
|
- benchmark/to_hugeint_profile.rb
|
|
112
|
+
- benchmark/to_intern_ips.rb
|
|
112
113
|
- bin/console
|
|
113
114
|
- bin/setup
|
|
114
115
|
- docker-compose.yml
|