duckdb 0.2.6.0 → 0.2.9.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 +27 -3
- data/.github/workflows/test_on_ubuntu.yml +17 -36
- data/.github/workflows/test_on_windows.yml +43 -0
- data/CHANGELOG.md +42 -0
- data/CONTRIBUTION.md +24 -0
- data/Gemfile.lock +3 -3
- data/README.md +84 -4
- data/duckdb.gemspec +2 -2
- data/ext/duckdb/appender.c +139 -3
- data/ext/duckdb/config.c +80 -0
- data/ext/duckdb/config.h +18 -0
- data/ext/duckdb/database.c +48 -2
- data/ext/duckdb/duckdb.c +6 -0
- data/ext/duckdb/extconf.rb +15 -0
- data/ext/duckdb/prepared_statement.c +26 -3
- data/ext/duckdb/result.c +67 -33
- data/ext/duckdb/ruby-duckdb.h +12 -0
- data/lib/duckdb/appender.rb +303 -0
- data/lib/duckdb/config.rb +65 -0
- data/lib/duckdb/connection.rb +21 -0
- data/lib/duckdb/database.rb +15 -2
- data/lib/duckdb/prepared_statement.rb +22 -4
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +2 -0
- metadata +13 -8
- data/.travis.yml +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: af998f52f46c0ef8f51501333cbaf39d720daaa389eb618d7d7ad79627d70ad9
|
4
|
+
data.tar.gz: 8e1c5323fa2f917c9ab6050a0350e5e25b646559492501f636af026b79cb20f8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 14809adeffb7bc79f2102e29f89a6fe6ea276ab38eaeabed9f3c18a023566c3bbad06c1ab31e55499e77d3f0f9ced186d618c24639b8c16ceff1ee61304f9f67
|
7
|
+
data.tar.gz: 15d164af6af9d985765d7b9fa87dcf7f9cf89fb2d691c9d44ea2d2bb72341a77213647cb08bcacc66094eb1622d250fe203f41a9529866af9f358518800f7183
|
@@ -7,7 +7,8 @@ jobs:
|
|
7
7
|
runs-on: macos-latest
|
8
8
|
strategy:
|
9
9
|
matrix:
|
10
|
-
ruby: ['2.
|
10
|
+
ruby: ['2.6.8', '2.7.4', '3.0.2', 'head']
|
11
|
+
duckdb: ['0.2.8', '0.2.9']
|
11
12
|
|
12
13
|
steps:
|
13
14
|
- uses: actions/checkout@v2
|
@@ -17,9 +18,32 @@ jobs:
|
|
17
18
|
with:
|
18
19
|
ruby-version: ${{ matrix.ruby }}
|
19
20
|
|
20
|
-
- name:
|
21
|
+
- name: duckdb cache
|
22
|
+
id: duckdb-cache
|
23
|
+
uses: actions/cache@v2
|
24
|
+
with:
|
25
|
+
path: /usr/local/Cellar/duckdb@${{ matrix.duckdb }}
|
26
|
+
key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
|
27
|
+
|
28
|
+
- name: Install duckdb v${{ matrix.duckdb }} by brew
|
29
|
+
env:
|
30
|
+
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
31
|
+
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
32
|
+
run: |
|
33
|
+
brew tap-new duckdb/taps
|
34
|
+
brew extract duckdb duckdb/taps --version $DUCKDB_VERSION
|
35
|
+
brew install duckdb/taps/duckdb@$DUCKDB_VERSION
|
36
|
+
|
37
|
+
- name: setup duckdb v${{ matrix.duckdb }} headers and libraries
|
38
|
+
env:
|
39
|
+
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
21
40
|
run: |
|
22
|
-
|
41
|
+
if [ ! -L /usr/local/include/duckdb.h ]; then
|
42
|
+
header=`find /usr/local/Cellar/duckdb@$DUCKDB_VERSION -name "duckdb.h"`
|
43
|
+
lib=`find /usr/local/Cellar/duckdb@$DUCKDB_VERSION -name "libduckdb.dylib"`
|
44
|
+
ln -s $header /usr/local/include/duckdb.h
|
45
|
+
ln -s $lib /usr/local/lib/libduckdb.dylib
|
46
|
+
fi
|
23
47
|
|
24
48
|
- name: Build and test with Rake with Ruby ${{ matrix.ruby }}
|
25
49
|
run: |
|
@@ -8,8 +8,8 @@ jobs:
|
|
8
8
|
runs-on: ubuntu-latest
|
9
9
|
strategy:
|
10
10
|
matrix:
|
11
|
-
ruby: ['2.
|
12
|
-
duckdb: ['0.2.
|
11
|
+
ruby: ['2.6.8', '2.7.4', '3.0.2', 'head']
|
12
|
+
duckdb: ['0.2.8', '0.2.9']
|
13
13
|
|
14
14
|
steps:
|
15
15
|
- uses: actions/checkout@v2
|
@@ -19,43 +19,24 @@ jobs:
|
|
19
19
|
with:
|
20
20
|
ruby-version: ${{ matrix.ruby }}
|
21
21
|
|
22
|
-
- name: duckdb
|
23
|
-
id: duckdb-cache
|
24
|
-
uses: actions/cache@
|
22
|
+
- name: duckdb cache
|
23
|
+
id: duckdb-cache
|
24
|
+
uses: actions/cache@v2
|
25
25
|
with:
|
26
|
-
path: duckdb-
|
27
|
-
key: ${{ runner.os }}-duckdb-
|
28
|
-
restore-keys: |
|
29
|
-
${{ runner.os }}-duckdb-v0_2_6
|
26
|
+
path: duckdb-v${{ matrix.duckdb }}
|
27
|
+
key: ${{ runner.os }}-duckdb-v${{ matrix.duckdb }}
|
30
28
|
|
31
|
-
- name: duckdb
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
path: duckdb-v0.2.5
|
36
|
-
key: ${{ runner.os }}-duckdb-v0_2_5_001
|
37
|
-
restore-keys: |
|
38
|
-
${{ runner.os }}-duckdb-v0_2_5
|
39
|
-
|
40
|
-
- name: Build duckdb 0.2.6
|
41
|
-
if: steps.duckdb-cache-v0_2_6.outputs.cache-hit != 'true'
|
42
|
-
run: |
|
43
|
-
git clone -b v0.2.6 https://github.com/cwida/duckdb.git duckdb-tmp-v0.2.6
|
44
|
-
cd duckdb-tmp-v0.2.6 && make && cd ..
|
45
|
-
rm -rf duckdb-v0.2.6
|
46
|
-
mkdir -p duckdb-v0.2.6/build/release/src duckdb-v0.2.6/src
|
47
|
-
cp -rip duckdb-tmp-v0.2.6/build/release/src/*.so duckdb-v0.2.6/build/release/src
|
48
|
-
cp -rip duckdb-tmp-v0.2.6/src/include duckdb-v0.2.6/src/
|
49
|
-
|
50
|
-
- name: Build duckdb 0.2.5
|
51
|
-
if: steps.duckdb-cache-v0_2_5.outputs.cache-hit != 'true'
|
29
|
+
- name: Build duckdb ${{ matrix.duckdb }}
|
30
|
+
env:
|
31
|
+
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
32
|
+
if: steps.duckdb-cache.outputs.cache-hit != 'true'
|
52
33
|
run: |
|
53
|
-
git clone -b
|
54
|
-
cd duckdb-tmp-
|
55
|
-
rm -rf duckdb-
|
56
|
-
mkdir -p duckdb-
|
57
|
-
cp -rip duckdb-tmp-
|
58
|
-
cp -rip duckdb-tmp-
|
34
|
+
git clone -b v$DUCKDB_VERSION https://github.com/cwida/duckdb.git duckdb-tmp-v$DUCKDB_VERSION
|
35
|
+
cd duckdb-tmp-v$DUCKDB_VERSION && make && cd ..
|
36
|
+
rm -rf duckdb-v$DUCKDB_VERSION
|
37
|
+
mkdir -p duckdb-v$DUCKDB_VERSION/build/release/src duckdb-v$DUCKDB_VERSION/src
|
38
|
+
cp -rip duckdb-tmp-v$DUCKDB_VERSION/build/release/src/*.so duckdb-v$DUCKDB_VERSION/build/release/src
|
39
|
+
cp -rip duckdb-tmp-v$DUCKDB_VERSION/src/include duckdb-v$DUCKDB_VERSION/src/
|
59
40
|
|
60
41
|
- name: Build and test with Rake with Ruby ${{ matrix.ruby }}
|
61
42
|
env:
|
@@ -0,0 +1,43 @@
|
|
1
|
+
name: Windows
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
build:
|
7
|
+
runs-on: windows-latest
|
8
|
+
strategy:
|
9
|
+
matrix:
|
10
|
+
ruby: ['2.6.8', '2.7.4', '3.0.2', 'head']
|
11
|
+
duckdb: ['0.2.8', '0.2.9']
|
12
|
+
|
13
|
+
steps:
|
14
|
+
- uses: actions/checkout@v2
|
15
|
+
|
16
|
+
- name: Set up Ruby
|
17
|
+
uses: ruby/setup-ruby@v1
|
18
|
+
with:
|
19
|
+
ruby-version: ${{ matrix.ruby }}
|
20
|
+
|
21
|
+
- name: download duckdb binary for windows 64bit
|
22
|
+
env:
|
23
|
+
DUCKDB_VERSION: ${{ matrix.duckdb }}
|
24
|
+
run: |
|
25
|
+
curl -OL https://github.com/duckdb/duckdb/releases/download/v${env:DUCKDB_VERSION}/libduckdb-windows-amd64.zip
|
26
|
+
|
27
|
+
- name: extract zip file
|
28
|
+
run: |
|
29
|
+
7z x libduckdb-windows-amd64.zip
|
30
|
+
|
31
|
+
- name: Build with Rake with Ruby ${{ matrix.ruby }}
|
32
|
+
run: |
|
33
|
+
bundle install
|
34
|
+
bundle exec rake build -- --with-duckdb-include=../../../.. --with-duckdb-lib=../../../..
|
35
|
+
- name: setup duckdb.dll
|
36
|
+
run: |
|
37
|
+
cp duckdb.dll C:/Windows/System32/
|
38
|
+
|
39
|
+
# FIXME: rake test fails with LoadError
|
40
|
+
# C:/hostedtoolcache/windows/Ruby/2.7.3/x64/lib/ruby/2.7.0/rubygems/core_ext/kernel_require.rb:83:in `require': 126: The specified module could not be found. - D:/a/ruby-duckdb/ruby-duckdb/lib/duckdb/duckdb_native.so (LoadError)`
|
41
|
+
- name: rake test
|
42
|
+
run: |
|
43
|
+
rake test
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,47 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
# 0.2.9.0
|
4
|
+
|
5
|
+
- add DuckDB::Appender#append
|
6
|
+
- breaking change.
|
7
|
+
- append_timestamp is called when the argument is Time object.
|
8
|
+
- append_date is called when the argument is Date object.
|
9
|
+
- add DuckDB::Appender#append_timestamp.
|
10
|
+
- add DuckDB::Appender#append_interval. append_interval is expremental.
|
11
|
+
- add DuckDB::Result#rows_changed
|
12
|
+
- refactoring DuckDB::Append#append_hugeint with duckdb v0.2.9
|
13
|
+
- test 2 versions of duckdb on github actions macos CI.
|
14
|
+
- fix windows CI failes
|
15
|
+
- update github actions CI on ubuntu
|
16
|
+
- fix to build with duckdb v0.2.9
|
17
|
+
- use duckdb_prepare_error when get error message of prepared statement.
|
18
|
+
- add DuckDB::Appender#append_date
|
19
|
+
- add DuckDB::Appender#append_time
|
20
|
+
|
21
|
+
# 0.2.8.0
|
22
|
+
|
23
|
+
- DuckDB::Database.open accepts 2-nd argument as DuckDB::Config object.
|
24
|
+
- add DuckDB::Config
|
25
|
+
- bump duckdb to 0.2.8 in CI
|
26
|
+
- bump Ruby to 2.6.8, 2.7.4, 3.0.2 in CI
|
27
|
+
|
28
|
+
# 0.2.7.0
|
29
|
+
|
30
|
+
- call duckdb_free after calling duckdb_value_blob, duckdb_value_varchar.
|
31
|
+
- bump DuckDB to v0.2.7 in CI
|
32
|
+
- rake build on Windows in github actions.
|
33
|
+
- There is a issue (LoadError) when running rake test on Windows (in GitHub actions).
|
34
|
+
|
35
|
+
# 0.2.6.1
|
36
|
+
|
37
|
+
- add DuckDB::PreparedStatement#bind_int8
|
38
|
+
- DuckDB::Connection#appender accepts block.
|
39
|
+
- add DuckDB::Appender#append_row.
|
40
|
+
- support HUGEINT type.
|
41
|
+
- add DuckDB::Appender#append.
|
42
|
+
- rename PreparedStatement#bind_boolean to PreparedStatement#bind_bool.
|
43
|
+
- add DuckDB::Connection#appender.
|
44
|
+
|
3
45
|
# 0.2.6.0
|
4
46
|
|
5
47
|
- change version policy
|
data/CONTRIBUTION.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# Contribution Guide
|
2
|
+
|
3
|
+
## Issue
|
4
|
+
|
5
|
+
If you spot a problem, [search if an issue already exists](https://github.com/suketa/ruby-duckdb/issues).
|
6
|
+
If a related issue doesn't exist, you can open a [new issue](https://github.com/suketa/ruby-duckdb/issues/new).
|
7
|
+
|
8
|
+
|
9
|
+
## Fix Issues or Add New Features.
|
10
|
+
|
11
|
+
1. install [Ruby](https://www.ruby-lang.org/) into your local machine.
|
12
|
+
2. install [duckdb](https://duckdb.org/) into your local machine.
|
13
|
+
3. fork the repository and `git clone` to your local machine.
|
14
|
+
4. run `bundle install`
|
15
|
+
5. run `rake build`
|
16
|
+
or you might run with C duckdb header and library directories:
|
17
|
+
`rake build -- --with-duckdb-include=/duckdb_header_directory --with-duckdb-lib=/duckdb_library_directory`
|
18
|
+
6. run `rake test`
|
19
|
+
7. create new branch to change the code.
|
20
|
+
8. change the code.
|
21
|
+
9. write test.
|
22
|
+
10. run `rake test` and confirm all tests pass.
|
23
|
+
11. git push.
|
24
|
+
12. create PR.
|
data/Gemfile.lock
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
duckdb (0.2.
|
4
|
+
duckdb (0.2.9.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
minitest (5.14.4)
|
10
|
-
rake (13.0.
|
10
|
+
rake (13.0.6)
|
11
11
|
rake-compiler (1.1.1)
|
12
12
|
rake
|
13
13
|
|
@@ -22,4 +22,4 @@ DEPENDENCIES
|
|
22
22
|
rake-compiler
|
23
23
|
|
24
24
|
BUNDLED WITH
|
25
|
-
2.2.
|
25
|
+
2.2.25
|
data/README.md
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
# ruby-duckdb
|
2
2
|
|
3
|
-
[![Build Status](https://travis-ci.com/suketa/ruby-duckdb.svg?branch=master)](https://travis-ci.com/suketa/ruby-duckdb)
|
4
3
|
[![](https://github.com/suketa/ruby-duckdb/workflows/Ubuntu/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AUbuntu)
|
5
4
|
[![](https://github.com/suketa/ruby-duckdb/workflows/MacOS/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AMacOS)
|
5
|
+
[![](https://github.com/suketa/ruby-duckdb/workflows/Windows/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AWindows)
|
6
6
|
|
7
7
|
## Description
|
8
8
|
|
@@ -18,10 +18,10 @@ You must have [DuckDB](http://www.duckdb.org) engine installed in order to build
|
|
18
18
|
gem install duckdb
|
19
19
|
```
|
20
20
|
|
21
|
-
or you must specify the location of the
|
21
|
+
or you must specify the location of the C header and library files:
|
22
22
|
|
23
23
|
```
|
24
|
-
gem install duckdb -- --with-duckdb-include=/
|
24
|
+
gem install duckdb -- --with-duckdb-include=/duckdb_header_directory --with-duckdb-lib=/duckdb_library_directory
|
25
25
|
```
|
26
26
|
|
27
27
|
## Usage
|
@@ -68,7 +68,7 @@ end
|
|
68
68
|
### using BLOB column
|
69
69
|
|
70
70
|
BLOB is available with DuckDB v0.2.5 or later.
|
71
|
-
Use `DuckDB::Blob.new` or use sting#force_encoding(Encoding::
|
71
|
+
Use `DuckDB::Blob.new` or use sting#force_encoding(Encoding::BINARY)
|
72
72
|
|
73
73
|
```
|
74
74
|
require 'duckdb'
|
@@ -87,3 +87,83 @@ DuckDB::Database.open do |db|
|
|
87
87
|
end
|
88
88
|
end
|
89
89
|
```
|
90
|
+
|
91
|
+
### Appender
|
92
|
+
|
93
|
+
Appender class provides Ruby interface of [DuckDB Appender](https://duckdb.org/docs/data/appender)
|
94
|
+
|
95
|
+
```
|
96
|
+
require 'duckdb'
|
97
|
+
require 'benchmark'
|
98
|
+
|
99
|
+
def insert
|
100
|
+
DuckDB::Database.open do |db|
|
101
|
+
db.connect do |con|
|
102
|
+
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
|
103
|
+
10000.times do
|
104
|
+
con.query("INSERT into users VALUES(1, 'Alice')")
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def prepare
|
111
|
+
DuckDB::Database.open do |db|
|
112
|
+
db.connect do |con|
|
113
|
+
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
|
114
|
+
stmt = con.prepared_statement('INSERT INTO users VALUES($1, $2)')
|
115
|
+
10000.times do
|
116
|
+
stmt.bind(1, 1)
|
117
|
+
stmt.bind(2, 'Alice')
|
118
|
+
stmt.execute
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def append
|
125
|
+
DuckDB::Database.open do |db|
|
126
|
+
db.connect do |con|
|
127
|
+
con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
|
128
|
+
appender = con.appender('users')
|
129
|
+
10000.times do
|
130
|
+
appender.begin_row
|
131
|
+
appender.append(1)
|
132
|
+
appender.append('Alice')
|
133
|
+
appender.end_row
|
134
|
+
end
|
135
|
+
appender.flush
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
Benchmark.bm(8) do |x|
|
141
|
+
x.report('insert') { insert }
|
142
|
+
x.report('prepare') { prepare }
|
143
|
+
x.report('append') { append }
|
144
|
+
end
|
145
|
+
|
146
|
+
# =>
|
147
|
+
# user system total real
|
148
|
+
# insert 0.637439 0.000000 0.637439 ( 0.637486 )
|
149
|
+
# prepare 0.230457 0.000000 0.230457 ( 0.230460 )
|
150
|
+
# append 0.012666 0.000000 0.012666 ( 0.012670 )
|
151
|
+
```
|
152
|
+
|
153
|
+
### Configuration
|
154
|
+
|
155
|
+
Config class provides Ruby interface of [DuckDB configuration](https://duckdb.org/docs/api/c/config).
|
156
|
+
|
157
|
+
```
|
158
|
+
require 'duckdb'
|
159
|
+
config = DuckDB::Config.new
|
160
|
+
config['default_order'] = 'DESC'
|
161
|
+
db = DuckDB::Database.open(nil, config)
|
162
|
+
con = db.connect
|
163
|
+
con.query('CREATE TABLE numbers (number INTEGER)')
|
164
|
+
con.query('INSERT INTO numbers VALUES (2), (1), (4), (3)')
|
165
|
+
|
166
|
+
# number is ordered by descending.
|
167
|
+
r = con.query('SELECT number FROM numbers ORDER BY number')
|
168
|
+
r.first.first # => 4
|
169
|
+
```
|
data/duckdb.gemspec
CHANGED
@@ -21,12 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
# Specify which files should be added to the gem when it is released.
|
23
23
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
-
spec.files = Dir.chdir(File.expand_path(
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
25
25
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
26
26
|
end
|
27
27
|
spec.require_paths = ['lib']
|
28
28
|
spec.extensions = ['ext/duckdb/extconf.rb']
|
29
|
-
spec.required_ruby_version = '>= 2.
|
29
|
+
spec.required_ruby_version = '>= 2.6.0'
|
30
30
|
|
31
31
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
32
32
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
data/ext/duckdb/appender.c
CHANGED
@@ -24,6 +24,27 @@ static VALUE appender_append_varchar(VALUE self, VALUE val);
|
|
24
24
|
static VALUE appender_append_varchar_length(VALUE self, VALUE val, VALUE len);
|
25
25
|
static VALUE appender_append_blob(VALUE self, VALUE val);
|
26
26
|
static VALUE appender_append_null(VALUE self);
|
27
|
+
|
28
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
29
|
+
static VALUE appender__append_date(VALUE self, VALUE yearval, VALUE monthval, VALUE dayval);
|
30
|
+
#endif
|
31
|
+
|
32
|
+
#ifdef HAVE_DUCKDB_APPEND_INTERVAL
|
33
|
+
static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VALUE micros);
|
34
|
+
#endif
|
35
|
+
|
36
|
+
#ifdef HAVE_DUCKDB_APPEND_TIME
|
37
|
+
static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
38
|
+
#endif
|
39
|
+
|
40
|
+
#ifdef HAVE_DUCKDB_APPEND_TIMESTAMP
|
41
|
+
static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
42
|
+
#endif
|
43
|
+
|
44
|
+
#ifdef HAVE_DUCKDB_APPEND_HUGEINT
|
45
|
+
static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper);
|
46
|
+
#endif
|
47
|
+
|
27
48
|
static VALUE appender_flush(VALUE self);
|
28
49
|
static VALUE appender_close(VALUE self);
|
29
50
|
|
@@ -112,7 +133,7 @@ static VALUE appender_append_int8(VALUE self, VALUE val) {
|
|
112
133
|
|
113
134
|
static VALUE appender_append_int16(VALUE self, VALUE val) {
|
114
135
|
rubyDuckDBAppender *ctx;
|
115
|
-
int16_t i16val = NUM2INT(val);
|
136
|
+
int16_t i16val = (int16_t)NUM2INT(val);
|
116
137
|
|
117
138
|
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
118
139
|
|
@@ -136,7 +157,7 @@ static VALUE appender_append_int32(VALUE self, VALUE val) {
|
|
136
157
|
|
137
158
|
static VALUE appender_append_int64(VALUE self, VALUE val) {
|
138
159
|
rubyDuckDBAppender *ctx;
|
139
|
-
int64_t i64val = NUM2LL(val);
|
160
|
+
int64_t i64val = (int64_t)NUM2LL(val);
|
140
161
|
|
141
162
|
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
142
163
|
|
@@ -184,7 +205,7 @@ static VALUE appender_append_uint32(VALUE self, VALUE val) {
|
|
184
205
|
|
185
206
|
static VALUE appender_append_uint64(VALUE self, VALUE val) {
|
186
207
|
rubyDuckDBAppender *ctx;
|
187
|
-
uint64_t ui64val = (
|
208
|
+
uint64_t ui64val = (uint64_t)NUM2ULL(val);
|
188
209
|
|
189
210
|
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
190
211
|
|
@@ -268,6 +289,106 @@ static VALUE appender_append_null(VALUE self) {
|
|
268
289
|
return self;
|
269
290
|
}
|
270
291
|
|
292
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
293
|
+
static VALUE appender__append_date(VALUE self, VALUE yearval, VALUE monthval, VALUE dayval) {
|
294
|
+
duckdb_date_struct dt_struct;
|
295
|
+
duckdb_date dt;
|
296
|
+
rubyDuckDBAppender *ctx;
|
297
|
+
|
298
|
+
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
299
|
+
dt_struct.year = NUM2INT(yearval);
|
300
|
+
dt_struct.month = NUM2INT(monthval);
|
301
|
+
dt_struct.day = NUM2INT(dayval);
|
302
|
+
dt = duckdb_to_date(dt_struct);
|
303
|
+
|
304
|
+
if (duckdb_append_date(ctx->appender, dt) == DuckDBError) {
|
305
|
+
rb_raise(eDuckDBError, "failed to append date");
|
306
|
+
}
|
307
|
+
return self;
|
308
|
+
}
|
309
|
+
#endif
|
310
|
+
|
311
|
+
#ifdef HAVE_DUCKDB_APPEND_INTERVAL
|
312
|
+
static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VALUE micros) {
|
313
|
+
duckdb_interval interval;
|
314
|
+
rubyDuckDBAppender *ctx;
|
315
|
+
|
316
|
+
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
317
|
+
interval.months = NUM2INT(months);
|
318
|
+
interval.days = NUM2INT(days);
|
319
|
+
interval.micros = NUM2LL(micros);
|
320
|
+
|
321
|
+
if (duckdb_append_interval(ctx->appender, interval) == DuckDBError) {
|
322
|
+
rb_raise(eDuckDBError, "failed to append interval");
|
323
|
+
}
|
324
|
+
return self;
|
325
|
+
}
|
326
|
+
#endif
|
327
|
+
|
328
|
+
#ifdef HAVE_DUCKDB_APPEND_TIME
|
329
|
+
static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
330
|
+
duckdb_time_struct time_st;
|
331
|
+
duckdb_time time;
|
332
|
+
rubyDuckDBAppender *ctx;
|
333
|
+
|
334
|
+
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
335
|
+
time_st.hour = NUM2INT(hour);
|
336
|
+
time_st.min = NUM2INT(min);
|
337
|
+
time_st.sec = NUM2INT(sec);
|
338
|
+
time_st.micros = NUM2INT(micros);
|
339
|
+
|
340
|
+
time = duckdb_to_time(time_st);
|
341
|
+
|
342
|
+
if (duckdb_append_time(ctx->appender, time) == DuckDBError) {
|
343
|
+
rb_raise(eDuckDBError, "failed to append time");
|
344
|
+
}
|
345
|
+
return self;
|
346
|
+
}
|
347
|
+
#endif
|
348
|
+
|
349
|
+
#ifdef HAVE_DUCKDB_APPEND_TIMESTAMP
|
350
|
+
static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
351
|
+
duckdb_timestamp_struct timestamp_st;
|
352
|
+
duckdb_timestamp timestamp;
|
353
|
+
|
354
|
+
rubyDuckDBAppender *ctx;
|
355
|
+
|
356
|
+
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
357
|
+
|
358
|
+
timestamp_st.date.year = NUM2INT(year);
|
359
|
+
timestamp_st.date.month = NUM2INT(month);
|
360
|
+
timestamp_st.date.day = NUM2INT(day);
|
361
|
+
timestamp_st.time.hour = NUM2INT(hour);
|
362
|
+
timestamp_st.time.min = NUM2INT(min);
|
363
|
+
timestamp_st.time.sec = NUM2INT(sec);
|
364
|
+
timestamp_st.time.micros = NUM2INT(micros);
|
365
|
+
|
366
|
+
timestamp = duckdb_to_timestamp(timestamp_st);
|
367
|
+
|
368
|
+
if (duckdb_append_timestamp(ctx->appender, timestamp) == DuckDBError) {
|
369
|
+
rb_raise(eDuckDBError, "failed to append timestamp");
|
370
|
+
}
|
371
|
+
return self;
|
372
|
+
}
|
373
|
+
#endif
|
374
|
+
|
375
|
+
#ifdef HAVE_DUCKDB_APPEND_HUGEINT
|
376
|
+
static VALUE appender__append_hugeint(VALUE self, VALUE lower, VALUE upper) {
|
377
|
+
duckdb_hugeint hugeint;
|
378
|
+
|
379
|
+
hugeint.lower = NUM2ULL(lower);
|
380
|
+
hugeint.upper = NUM2LL(upper);
|
381
|
+
|
382
|
+
rubyDuckDBAppender *ctx;
|
383
|
+
|
384
|
+
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
385
|
+
if (duckdb_append_hugeint(ctx->appender, hugeint) == DuckDBError) {
|
386
|
+
rb_raise(eDuckDBError, "failed to append hugeint");
|
387
|
+
}
|
388
|
+
return self;
|
389
|
+
}
|
390
|
+
#endif
|
391
|
+
|
271
392
|
static VALUE appender_flush(VALUE self) {
|
272
393
|
rubyDuckDBAppender *ctx;
|
273
394
|
Data_Get_Struct(self, rubyDuckDBAppender, ctx);
|
@@ -309,6 +430,21 @@ void init_duckdb_appender(void) {
|
|
309
430
|
rb_define_method(cDuckDBAppender, "append_varchar_length", appender_append_varchar_length, 2);
|
310
431
|
rb_define_method(cDuckDBAppender, "append_blob", appender_append_blob, 1);
|
311
432
|
rb_define_method(cDuckDBAppender, "append_null", appender_append_null, 0);
|
433
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
434
|
+
rb_define_private_method(cDuckDBAppender, "_append_date", appender__append_date, 3);
|
435
|
+
#endif
|
436
|
+
#ifdef HAVE_DUCKDB_APPEND_INTERVAL
|
437
|
+
rb_define_private_method(cDuckDBAppender, "_append_interval", appender__append_interval, 3);
|
438
|
+
#endif
|
439
|
+
#ifdef HAVE_DUCKDB_APPEND_TIME
|
440
|
+
rb_define_private_method(cDuckDBAppender, "_append_time", appender__append_time, 4);
|
441
|
+
#endif
|
442
|
+
#ifdef HAVE_DUCKDB_APPEND_TIMESTAMP
|
443
|
+
rb_define_private_method(cDuckDBAppender, "_append_timestamp", appender__append_timestamp, 7);
|
444
|
+
#endif
|
445
|
+
#ifdef HAVE_DUCKDB_APPEND_HUGEINT
|
446
|
+
rb_define_private_method(cDuckDBAppender, "_append_hugeint", appender__append_hugeint, 2);
|
447
|
+
#endif
|
312
448
|
rb_define_method(cDuckDBAppender, "flush", appender_flush, 0);
|
313
449
|
rb_define_method(cDuckDBAppender, "close", appender_close, 0);
|
314
450
|
}
|
data/ext/duckdb/config.c
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#include "ruby-duckdb.h"
|
2
|
+
|
3
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
4
|
+
|
5
|
+
VALUE cDuckDBConfig;
|
6
|
+
|
7
|
+
static void deallocate(void *);
|
8
|
+
static VALUE allocate(VALUE klass);
|
9
|
+
static VALUE config_s_size(VALUE klass);
|
10
|
+
static VALUE config_s_get_config_flag(VALUE self, VALUE value);
|
11
|
+
static VALUE config_initialize(VALUE self);
|
12
|
+
static VALUE config_set_config(VALUE self, VALUE key, VALUE value);
|
13
|
+
|
14
|
+
static void deallocate(void * ctx)
|
15
|
+
{
|
16
|
+
rubyDuckDBConfig *p = (rubyDuckDBConfig *)ctx;
|
17
|
+
|
18
|
+
duckdb_destroy_config(&(p->config));
|
19
|
+
xfree(p);
|
20
|
+
}
|
21
|
+
|
22
|
+
static VALUE allocate(VALUE klass)
|
23
|
+
{
|
24
|
+
rubyDuckDBConfig *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBConfig));
|
25
|
+
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
|
26
|
+
}
|
27
|
+
|
28
|
+
static VALUE config_initialize(VALUE self) {
|
29
|
+
rubyDuckDBConfig *ctx;
|
30
|
+
|
31
|
+
Data_Get_Struct(self, rubyDuckDBConfig, ctx);
|
32
|
+
|
33
|
+
if (duckdb_create_config(&(ctx->config)) == DuckDBError) {
|
34
|
+
rb_raise(eDuckDBError, "failed to create config");
|
35
|
+
}
|
36
|
+
return self;
|
37
|
+
}
|
38
|
+
|
39
|
+
static VALUE config_s_size(VALUE self) {
|
40
|
+
return ULONG2NUM(duckdb_config_count());
|
41
|
+
}
|
42
|
+
|
43
|
+
static VALUE config_s_get_config_flag(VALUE klass, VALUE value) {
|
44
|
+
const char *pkey;
|
45
|
+
const char *pdesc;
|
46
|
+
|
47
|
+
size_t i = NUM2INT(value);
|
48
|
+
|
49
|
+
if (duckdb_get_config_flag(i, &pkey, &pdesc) == DuckDBError) {
|
50
|
+
rb_raise(eDuckDBError, "failed to get config information of index %ld", i);
|
51
|
+
}
|
52
|
+
|
53
|
+
return rb_ary_new3(2, rb_str_new2(pkey), rb_str_new2(pdesc));
|
54
|
+
}
|
55
|
+
|
56
|
+
static VALUE config_set_config(VALUE self, VALUE key, VALUE value) {
|
57
|
+
const char *pkey = StringValuePtr(key);
|
58
|
+
const char *pval = StringValuePtr(value);
|
59
|
+
|
60
|
+
rubyDuckDBConfig *ctx;
|
61
|
+
Data_Get_Struct(self, rubyDuckDBConfig, ctx);
|
62
|
+
|
63
|
+
if (duckdb_set_config(ctx->config, pkey, pval) == DuckDBError) {
|
64
|
+
rb_raise(eDuckDBError, "failed to set config %s => %s", pkey, pval);
|
65
|
+
}
|
66
|
+
return self;
|
67
|
+
}
|
68
|
+
|
69
|
+
void init_duckdb_config(void) {
|
70
|
+
cDuckDBConfig = rb_define_class_under(mDuckDB, "Config", rb_cObject);
|
71
|
+
rb_define_alloc_func(cDuckDBConfig, allocate);
|
72
|
+
rb_define_singleton_method(cDuckDBConfig, "size", config_s_size, 0);
|
73
|
+
rb_define_singleton_method(cDuckDBConfig, "get_config_flag", config_s_get_config_flag, 1);
|
74
|
+
|
75
|
+
rb_define_method(cDuckDBConfig, "initialize", config_initialize, 0);
|
76
|
+
rb_define_method(cDuckDBConfig, "set_config", config_set_config, 2);
|
77
|
+
}
|
78
|
+
|
79
|
+
#endif
|
80
|
+
|
data/ext/duckdb/config.h
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#ifndef RUBY_DUCKDB_CONFIG_H
|
2
|
+
#define RUBY_DUCKDB_CONFIG_H
|
3
|
+
|
4
|
+
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
5
|
+
|
6
|
+
struct _rubyDuckDBConfig {
|
7
|
+
duckdb_config config;
|
8
|
+
};
|
9
|
+
|
10
|
+
typedef struct _rubyDuckDBConfig rubyDuckDBConfig;
|
11
|
+
|
12
|
+
void init_duckdb_config(void);
|
13
|
+
|
14
|
+
#endif
|
15
|
+
|
16
|
+
#endif
|
17
|
+
|
18
|
+
|