duckdb 0.0.10 → 0.2.7.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c714dfd673f10a53f717920a00ce3a8d1bd60bb31eaa7c3d678427216ef8446d
4
- data.tar.gz: 8f8df0fa662a682fc977429c25a6ee41885ca4df603edfcc25cc46f960b1256a
3
+ metadata.gz: 309d9f5ae00645a93cd5bf8bd706f12391e1386336516d172e1963b963df5ab4
4
+ data.tar.gz: 8814748ae38a1b501d21b69f47b262124771ddc382dfcdbba3d7b3b88b3cb691
5
5
  SHA512:
6
- metadata.gz: e67c083420270093e6a026037527f5e10273404d0666b155ee0afd5c7e308ceae268c46ef1f878b9b6a656dec6b97e048488b85be53f715d9253e1806f8601a0
7
- data.tar.gz: a4501b2e7dc651147564da772f60f32dafbb21ddf846680128406ad9b64dbb6874ea3b6c15cd6e5226d35745680fb7f906eca7d0c8a72bf418594c7cd2486f53
6
+ metadata.gz: 96d87f3dfa1e8366e98a0a93e1f6506508c885131eb4287ec2463eea8040fb1cc87436a10871cecb83b524d97173443d9b1c42330a5f311c210ffb921b64a7d9
7
+ data.tar.gz: fed84bbde6a9c6b696e9a52bf769810788b7b49d845ddca065cafcfc535540d62127d395524ca4fee86cfba9213c82fe74204063ea674d14498d7f82f0c34e33
@@ -0,0 +1,28 @@
1
+ name: MacOS
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: macos-latest
8
+ strategy:
9
+ matrix:
10
+ ruby: ['2.5.8', '2.6.7', '2.7.3', '3.0.1', 'head']
11
+
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+
20
+ - name: Install latest duckdb by brew
21
+ run: |
22
+ brew install duckdb
23
+
24
+ - name: Build and test with Rake with Ruby ${{ matrix.ruby }}
25
+ run: |
26
+ ruby -v
27
+ bundle install --jobs 4 --retry 3
28
+ bundle exec rake
@@ -0,0 +1,66 @@
1
+ name: Ubuntu
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+
8
+ runs-on: ubuntu-latest
9
+ strategy:
10
+ matrix:
11
+ ruby: ['2.5.8', '2.6.7', '2.7.3', '3.0.1', 'head']
12
+ duckdb: ['0.2.6', '0.2.7']
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+
17
+ - name: Set up Ruby
18
+ uses: ruby/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby }}
21
+
22
+ - name: duckdb 0.2.6 cache
23
+ id: duckdb-cache-v0_2_6
24
+ uses: actions/cache@v1.1.0
25
+ with:
26
+ path: duckdb-v0.2.6
27
+ key: ${{ runner.os }}-duckdb-v0_2_6_001
28
+ restore-keys: |
29
+ ${{ runner.os }}-duckdb-v0_2_6
30
+
31
+ - name: duckdb 0.2.7 cache
32
+ id: duckdb-cache-v0_2_7
33
+ uses: actions/cache@v1.1.0
34
+ with:
35
+ path: duckdb-v0.2.7
36
+ key: ${{ runner.os }}-duckdb-v0_2_7_001
37
+ restore-keys: |
38
+ ${{ runner.os }}-duckdb-v0_2_7
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.7
51
+ if: steps.duckdb-cache-v0_2_7.outputs.cache-hit != 'true'
52
+ run: |
53
+ git clone -b v0.2.7 https://github.com/cwida/duckdb.git duckdb-tmp-v0.2.7
54
+ cd duckdb-tmp-v0.2.7 && make && cd ..
55
+ rm -rf duckdb-v0.2.7
56
+ mkdir -p duckdb-v0.2.7/build/release/src duckdb-v0.2.7/src
57
+ cp -rip duckdb-tmp-v0.2.7/build/release/src/*.so duckdb-v0.2.7/build/release/src
58
+ cp -rip duckdb-tmp-v0.2.7/src/include duckdb-v0.2.7/src/
59
+
60
+ - name: Build and test with Rake with Ruby ${{ matrix.ruby }}
61
+ env:
62
+ DUCKDB_VERSION: ${{ matrix.duckdb }}
63
+ run: |
64
+ gem install bundler
65
+ bundle install --jobs 4 --retry 3
66
+ bundle exec rake -- --with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src/
@@ -0,0 +1,37 @@
1
+ name: Windows
2
+
3
+ on: [push]
4
+
5
+ jobs:
6
+ build:
7
+ runs-on: windows-latest
8
+ strategy:
9
+ matrix:
10
+ ruby: ['2.5.8', '2.6.7', '2.7.3', '3.0.1', 'head']
11
+
12
+ steps:
13
+ - uses: actions/checkout@v2
14
+
15
+ - name: Set up Ruby
16
+ uses: ruby/setup-ruby@v1
17
+ with:
18
+ ruby-version: ${{ matrix.ruby }}
19
+
20
+ - name: download duckdb binary for windows 64bit
21
+ run: |
22
+ curl -OL https://github.com/duckdb/duckdb/releases/download/v0.2.6/libduckdb-windows-amd64.zip
23
+
24
+ - name: extract zip file
25
+ run: |
26
+ 7z x libduckdb-windows-amd64.zip
27
+
28
+ - name: Build with Rake with Ruby ${{ matrix.ruby }}
29
+ run: |
30
+ bundle install
31
+ bundle exec rake build -- --with-duckdb-include=../../../.. --with-duckdb-lib=../../../..
32
+
33
+ # FIXME: rake test fails with LoadError
34
+ # 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)`
35
+ # - name: rake test
36
+ # run: |
37
+ # rake test
data/.travis.yml CHANGED
@@ -2,16 +2,17 @@ language: ruby
2
2
  cache:
3
3
  bundler: true
4
4
  directories:
5
- - ${HOME}/duckdb-v0.2.2
5
+ - ${HOME}/duckdb-v0.2.7
6
6
  before_install:
7
7
  - yes | gem update --system
8
- - if [[ ! -d ${HOME}/duckdb-v0.2.2/build ]]; then cd ${HOME} && git clone -b v0.2.2 https://github.com/cwida/duckdb.git duckdb-v0.2.2 && cd duckdb-v0.2.2 && make && cd ${TRAVIS_BUILD_DIR}; fi
8
+ - if [[ ! -d ${HOME}/duckdb-v0.2.7/build ]]; then cd ${HOME} && git clone -b v0.2.7 https://github.com/cwida/duckdb.git duckdb-v0.2.7 && cd duckdb-v0.2.7 && make && cd ${TRAVIS_BUILD_DIR}; fi
9
9
 
10
10
  env:
11
- - DUCKDB_VERSION=0.2.2
11
+ - DUCKDB_VERSION=0.2.7
12
12
  rvm:
13
13
  - 2.5.8
14
- - 2.6.6
15
- - 2.7.2
14
+ - 2.6.7
15
+ - 2.7.3
16
+ - 3.0.1
16
17
  - ruby-head
17
18
  script: bundle exec rake -- --with-duckdb-include=${HOME}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${HOME}/duckdb-v${DUCKDB_VERSION}/build/release/src/
data/CHANGELOG.md CHANGED
@@ -1,9 +1,48 @@
1
1
  # ChangeLog
2
2
 
3
+ # 0.2.7.0
4
+
5
+ - call duckdb_free after calling duckdb_value_blob, duckdb_value_varchar.
6
+ - bump DuckDB to v0.2.7 in CI
7
+ - rake build on Windows in github actions.
8
+ - There is a issue (LoadError) when running rake test on Windows (in GitHub actions).
9
+
10
+ # 0.2.6.1
11
+
12
+ - add DuckDB::PreparedStatement#bind_int8
13
+ - DuckDB::Connection#appender accepts block.
14
+ - add DuckDB::Appender#append_row.
15
+ - support HUGEINT type.
16
+ - add DuckDB::Appender#append.
17
+ - rename PreparedStatement#bind_boolean to PreparedStatement#bind_bool.
18
+ - add DuckDB::Connection#appender.
19
+
20
+ # 0.2.6.0
21
+
22
+ - change version policy
23
+ - ruby-duckdb W.X.Y.Z supports duckdb W.X.Y
24
+ - add DuckDB::Appender
25
+ - bump DuckDB to v0.2.6 in CI.
26
+ - remove unnecessary duckdb header file from MacOS CI.
27
+ - add DuckDB::Connection#prepared_statement.
28
+
29
+ ## 0.0.12
30
+
31
+ - bump DuckDB to v0.2.5
32
+ - support BLOB type (with DuckDB version 0.2.5 or later)
33
+
34
+ ## 0.0.11
35
+
36
+ - fix failure in test_close in test/duckdb_test/database_test.rb because DuckDB error message was changed.
37
+ - bump DuckDb to v0.2.4
38
+ - add test CI with Ruby 3.0.0
39
+ - add test CI on MacOS.
40
+ - bunp DuckDB to v0.2.3
41
+
3
42
  ## 0.0.10
4
43
 
5
44
  - bump DuckDB to v0.2.2
6
- - fix to build failure on MAC OS/X
45
+ - fix to build failure on MacOS.
7
46
 
8
47
  ## 0.0.9
9
48
 
data/Gemfile.lock CHANGED
@@ -1,18 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (0.0.10)
4
+ duckdb (0.2.7.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- minitest (5.14.2)
10
- rake (13.0.1)
9
+ minitest (5.14.4)
10
+ rake (13.0.3)
11
11
  rake-compiler (1.1.1)
12
12
  rake
13
13
 
14
14
  PLATFORMS
15
- ruby
15
+ x86_64-linux
16
16
 
17
17
  DEPENDENCIES
18
18
  bundler (~> 2.0)
@@ -22,4 +22,4 @@ DEPENDENCIES
22
22
  rake-compiler
23
23
 
24
24
  BUNDLED WITH
25
- 2.1.4
25
+ 2.2.17
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.com/suketa/ruby-duckdb.svg?branch=master)](https://travis-ci.com/suketa/ruby-duckdb)
4
4
  [![](https://github.com/suketa/ruby-duckdb/workflows/Ubuntu/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AUbuntu)
5
+ [![](https://github.com/suketa/ruby-duckdb/workflows/MacOS/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AMacOS)
5
6
 
6
7
  ## Description
7
8
 
@@ -63,3 +64,88 @@ DuckDB::Database.open do |db|
63
64
  end
64
65
  end
65
66
  ```
67
+
68
+ ### using BLOB column
69
+
70
+ BLOB is available with DuckDB v0.2.5 or later.
71
+ Use `DuckDB::Blob.new` or use sting#force_encoding(Encoding::BINARY)
72
+
73
+ ```
74
+ require 'duckdb'
75
+
76
+ DuckDB::Database.open do |db|
77
+ db.connect do |con|
78
+ con.query('CREATE TABLE blob_table (binary_data BLOB)')
79
+ stmt = DuckDB::PreparedStatement.new(con, 'INSERT INTO blob_table VALUES ($1)')
80
+
81
+ stmt.bind(1, DuckDB::Blob.new("\0\1\2\3\4\5"))
82
+ # stmt.bind(1, "\0\1\2\3\4\5".force_encoding(Encoding::BINARY))
83
+ stmt.execute
84
+
85
+ result = con.query('SELECT binary_data FROM blob_table')
86
+ p result.first.first
87
+ end
88
+ end
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
+ ```
@@ -0,0 +1,315 @@
1
+ #include "ruby-duckdb.h"
2
+
3
+ #ifdef HAVE_DUCKDB_APPENDER_CREATE
4
+
5
+ static VALUE cDuckDBAppender;
6
+
7
+ static void deallocate(void *);
8
+ static VALUE allocate(VALUE klass);
9
+ static VALUE appender_initialize(VALUE klass, VALUE con, VALUE schema, VALUE table);
10
+ static VALUE appender_begin_row(VALUE self);
11
+ static VALUE appender_end_row(VALUE self);
12
+ static VALUE appender_append_bool(VALUE self, VALUE val);
13
+ static VALUE appender_append_int8(VALUE self, VALUE val);
14
+ static VALUE appender_append_int16(VALUE self, VALUE val);
15
+ static VALUE appender_append_int32(VALUE self, VALUE val);
16
+ static VALUE appender_append_int64(VALUE self, VALUE val);
17
+ static VALUE appender_append_uint8(VALUE self, VALUE val);
18
+ static VALUE appender_append_uint16(VALUE self, VALUE val);
19
+ static VALUE appender_append_uint32(VALUE self, VALUE val);
20
+ static VALUE appender_append_uint64(VALUE self, VALUE val);
21
+ static VALUE appender_append_float(VALUE self, VALUE val);
22
+ static VALUE appender_append_double(VALUE self, VALUE val);
23
+ static VALUE appender_append_varchar(VALUE self, VALUE val);
24
+ static VALUE appender_append_varchar_length(VALUE self, VALUE val, VALUE len);
25
+ static VALUE appender_append_blob(VALUE self, VALUE val);
26
+ static VALUE appender_append_null(VALUE self);
27
+ static VALUE appender_flush(VALUE self);
28
+ static VALUE appender_close(VALUE self);
29
+
30
+ static void deallocate(void * ctx)
31
+ {
32
+ rubyDuckDBAppender *p = (rubyDuckDBAppender *)ctx;
33
+
34
+ duckdb_appender_destroy(&(p->appender));
35
+ xfree(p);
36
+ }
37
+
38
+ static VALUE allocate(VALUE klass)
39
+ {
40
+ rubyDuckDBAppender *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBAppender));
41
+ return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
42
+ }
43
+
44
+ static VALUE appender_initialize(VALUE self, VALUE con, VALUE schema, VALUE table) {
45
+
46
+ rubyDuckDBConnection *ctxcon;
47
+ rubyDuckDBAppender *ctx;
48
+ char *pschema = 0;
49
+
50
+ if (!rb_obj_is_kind_of(con, cDuckDBConnection)) {
51
+ rb_raise(rb_eTypeError, "1st argument should be instance of DackDB::Connection");
52
+ }
53
+
54
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
55
+ Data_Get_Struct(con, rubyDuckDBConnection, ctxcon);
56
+
57
+ if (schema != Qnil) {
58
+ pschema = StringValuePtr(schema);
59
+ }
60
+
61
+ if (duckdb_appender_create(ctxcon->con, pschema, StringValuePtr(table), &(ctx->appender)) == DuckDBError) {
62
+ rb_raise(eDuckDBError, "failed to create appender");
63
+ }
64
+ return self;
65
+ }
66
+
67
+ static VALUE appender_begin_row(VALUE self) {
68
+ rubyDuckDBAppender *ctx;
69
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
70
+
71
+ if (duckdb_appender_begin_row(ctx->appender) == DuckDBError) {
72
+ rb_raise(eDuckDBError, "failed to flush");
73
+ }
74
+ return self;
75
+ }
76
+
77
+ static VALUE appender_end_row(VALUE self) {
78
+ rubyDuckDBAppender *ctx;
79
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
80
+
81
+ if (duckdb_appender_end_row(ctx->appender) == DuckDBError) {
82
+ rb_raise(eDuckDBError, "failed to flush");
83
+ }
84
+ return self;
85
+ }
86
+
87
+ static VALUE appender_append_bool(VALUE self, VALUE val) {
88
+ rubyDuckDBAppender *ctx;
89
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
90
+
91
+ if (val != Qtrue && val != Qfalse) {
92
+ rb_raise(rb_eArgError, "argument must be boolean");
93
+ }
94
+
95
+ if (duckdb_append_bool(ctx->appender, (val == Qtrue)) == DuckDBError) {
96
+ rb_raise(eDuckDBError, "failed to append boolean");
97
+ }
98
+ return self;
99
+ }
100
+
101
+ static VALUE appender_append_int8(VALUE self, VALUE val) {
102
+ rubyDuckDBAppender *ctx;
103
+ int8_t i8val = (int8_t)NUM2INT(val);
104
+
105
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
106
+
107
+ if (duckdb_append_int8(ctx->appender, i8val) == DuckDBError) {
108
+ rb_raise(eDuckDBError, "failed to append");
109
+ }
110
+ return self;
111
+ }
112
+
113
+ static VALUE appender_append_int16(VALUE self, VALUE val) {
114
+ rubyDuckDBAppender *ctx;
115
+ int16_t i16val = (int16_t)NUM2INT(val);
116
+
117
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
118
+
119
+ if (duckdb_append_int16(ctx->appender, i16val) == DuckDBError) {
120
+ rb_raise(eDuckDBError, "failed to append");
121
+ }
122
+ return self;
123
+ }
124
+
125
+ static VALUE appender_append_int32(VALUE self, VALUE val) {
126
+ rubyDuckDBAppender *ctx;
127
+ int32_t i32val = (int32_t)NUM2INT(val);
128
+
129
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
130
+
131
+ if (duckdb_append_int32(ctx->appender, i32val) == DuckDBError) {
132
+ rb_raise(eDuckDBError, "failed to append");
133
+ }
134
+ return self;
135
+ }
136
+
137
+ static VALUE appender_append_int64(VALUE self, VALUE val) {
138
+ rubyDuckDBAppender *ctx;
139
+ int64_t i64val = (int64_t)NUM2LL(val);
140
+
141
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
142
+
143
+ if (duckdb_append_int64(ctx->appender, i64val) == DuckDBError) {
144
+ rb_raise(eDuckDBError, "failed to append");
145
+ }
146
+ return self;
147
+ }
148
+
149
+ static VALUE appender_append_uint8(VALUE self, VALUE val) {
150
+ rubyDuckDBAppender *ctx;
151
+ int8_t ui8val = (uint8_t)NUM2UINT(val);
152
+
153
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
154
+
155
+ if (duckdb_append_uint8(ctx->appender, ui8val) == DuckDBError) {
156
+ rb_raise(eDuckDBError, "failed to append");
157
+ }
158
+ return self;
159
+ }
160
+
161
+ static VALUE appender_append_uint16(VALUE self, VALUE val) {
162
+ rubyDuckDBAppender *ctx;
163
+ uint16_t ui16val = (uint16_t)NUM2UINT(val);
164
+
165
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
166
+
167
+ if (duckdb_append_uint16(ctx->appender, ui16val) == DuckDBError) {
168
+ rb_raise(eDuckDBError, "failed to append");
169
+ }
170
+ return self;
171
+ }
172
+
173
+ static VALUE appender_append_uint32(VALUE self, VALUE val) {
174
+ rubyDuckDBAppender *ctx;
175
+ uint32_t ui32val = (uint32_t)NUM2UINT(val);
176
+
177
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
178
+
179
+ if (duckdb_append_uint32(ctx->appender, ui32val) == DuckDBError) {
180
+ rb_raise(eDuckDBError, "failed to append");
181
+ }
182
+ return self;
183
+ }
184
+
185
+ static VALUE appender_append_uint64(VALUE self, VALUE val) {
186
+ rubyDuckDBAppender *ctx;
187
+ uint64_t ui64val = (uint64_t)NUM2ULL(val);
188
+
189
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
190
+
191
+ if (duckdb_append_uint64(ctx->appender, ui64val) == DuckDBError) {
192
+ rb_raise(eDuckDBError, "failed to append");
193
+ }
194
+ return self;
195
+ }
196
+
197
+ static VALUE appender_append_float(VALUE self, VALUE val) {
198
+ rubyDuckDBAppender *ctx;
199
+ float fval = (float)NUM2DBL(val);
200
+
201
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
202
+
203
+ if (duckdb_append_float(ctx->appender, fval) == DuckDBError) {
204
+ rb_raise(eDuckDBError, "failed to append");
205
+ }
206
+ return self;
207
+ }
208
+
209
+ static VALUE appender_append_double(VALUE self, VALUE val) {
210
+ rubyDuckDBAppender *ctx;
211
+ double dval = NUM2DBL(val);
212
+
213
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
214
+
215
+ if (duckdb_append_double(ctx->appender, dval) == DuckDBError) {
216
+ rb_raise(eDuckDBError, "failed to append");
217
+ }
218
+ return self;
219
+ }
220
+
221
+ static VALUE appender_append_varchar(VALUE self, VALUE val) {
222
+ rubyDuckDBAppender *ctx;
223
+ char *pval = StringValuePtr(val);
224
+
225
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
226
+
227
+ if (duckdb_append_varchar(ctx->appender, pval) == DuckDBError) {
228
+ rb_raise(eDuckDBError, "failed to append");
229
+ }
230
+ return self;
231
+ }
232
+
233
+ static VALUE appender_append_varchar_length(VALUE self, VALUE val, VALUE len) {
234
+ rubyDuckDBAppender *ctx;
235
+
236
+ char *pval = StringValuePtr(val);
237
+ idx_t length = (idx_t)NUM2ULL(len);
238
+
239
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
240
+
241
+ if (duckdb_append_varchar_length(ctx->appender, pval, length) == DuckDBError) {
242
+ rb_raise(eDuckDBError, "failed to append");
243
+ }
244
+ return self;
245
+ }
246
+
247
+ static VALUE appender_append_blob(VALUE self, VALUE val) {
248
+ rubyDuckDBAppender *ctx;
249
+
250
+ char *pval = StringValuePtr(val);
251
+ idx_t length = (idx_t)RSTRING_LEN(val);
252
+
253
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
254
+
255
+ if (duckdb_append_blob(ctx->appender, (void *)pval, length) == DuckDBError) {
256
+ rb_raise(eDuckDBError, "failed to append");
257
+ }
258
+ return self;
259
+ }
260
+
261
+ static VALUE appender_append_null(VALUE self) {
262
+ rubyDuckDBAppender *ctx;
263
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
264
+
265
+ if (duckdb_append_null(ctx->appender) == DuckDBError) {
266
+ rb_raise(eDuckDBError, "failed to append");
267
+ }
268
+ return self;
269
+ }
270
+
271
+ static VALUE appender_flush(VALUE self) {
272
+ rubyDuckDBAppender *ctx;
273
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
274
+
275
+ if (duckdb_appender_flush(ctx->appender) == DuckDBError) {
276
+ rb_raise(eDuckDBError, "failed to flush");
277
+ }
278
+ return self;
279
+ }
280
+
281
+ static VALUE appender_close(VALUE self) {
282
+ rubyDuckDBAppender *ctx;
283
+ Data_Get_Struct(self, rubyDuckDBAppender, ctx);
284
+
285
+ if (duckdb_appender_close(ctx->appender) == DuckDBError) {
286
+ rb_raise(eDuckDBError, "failed to flush");
287
+ }
288
+ return self;
289
+ }
290
+
291
+ void init_duckdb_appender(void) {
292
+ cDuckDBAppender = rb_define_class_under(mDuckDB, "Appender", rb_cObject);
293
+ rb_define_alloc_func(cDuckDBAppender, allocate);
294
+ rb_define_method(cDuckDBAppender, "initialize", appender_initialize, 3);
295
+ rb_define_method(cDuckDBAppender, "begin_row", appender_begin_row, 0);
296
+ rb_define_method(cDuckDBAppender, "end_row", appender_end_row, 0);
297
+ rb_define_method(cDuckDBAppender, "append_bool", appender_append_bool, 1);
298
+ rb_define_method(cDuckDBAppender, "append_int8", appender_append_int8, 1);
299
+ rb_define_method(cDuckDBAppender, "append_int16", appender_append_int16, 1);
300
+ rb_define_method(cDuckDBAppender, "append_int32", appender_append_int32, 1);
301
+ rb_define_method(cDuckDBAppender, "append_int64", appender_append_int64, 1);
302
+ rb_define_method(cDuckDBAppender, "append_uint8", appender_append_uint8, 1);
303
+ rb_define_method(cDuckDBAppender, "append_uint16", appender_append_uint16, 1);
304
+ rb_define_method(cDuckDBAppender, "append_uint32", appender_append_uint32, 1);
305
+ rb_define_method(cDuckDBAppender, "append_uint64", appender_append_uint64, 1);
306
+ rb_define_method(cDuckDBAppender, "append_float", appender_append_float, 1);
307
+ rb_define_method(cDuckDBAppender, "append_double", appender_append_double, 1);
308
+ rb_define_method(cDuckDBAppender, "append_varchar", appender_append_varchar, 1);
309
+ rb_define_method(cDuckDBAppender, "append_varchar_length", appender_append_varchar_length, 2);
310
+ rb_define_method(cDuckDBAppender, "append_blob", appender_append_blob, 1);
311
+ rb_define_method(cDuckDBAppender, "append_null", appender_append_null, 0);
312
+ rb_define_method(cDuckDBAppender, "flush", appender_flush, 0);
313
+ rb_define_method(cDuckDBAppender, "close", appender_close, 0);
314
+ }
315
+ #endif /* HAVE_DUCKDB_APPENDER_CREATE */
@@ -0,0 +1,17 @@
1
+ #ifndef RUBY_DUCKDB_APPENDER_H
2
+ #define RUBY_DUCKDB_APPENDER_H
3
+
4
+ #ifdef HAVE_DUCKDB_APPENDER_CREATE
5
+
6
+ struct _rubyDuckDBAppender {
7
+ duckdb_appender appender;
8
+ };
9
+
10
+ typedef struct _rubyDuckDBAppender rubyDuckDBAppender;
11
+
12
+ void init_duckdb_appender(void);
13
+
14
+ #endif
15
+
16
+ #endif
17
+
data/ext/duckdb/blob.c ADDED
@@ -0,0 +1,11 @@
1
+ #include "ruby-duckdb.h"
2
+
3
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
4
+
5
+ VALUE cDuckDBBlob;
6
+
7
+ void init_duckdb_blob(void)
8
+ {
9
+ cDuckDBBlob = rb_define_class_under(mDuckDB, "Blob", rb_cString);
10
+ }
11
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
data/ext/duckdb/blob.h ADDED
@@ -0,0 +1,14 @@
1
+ #ifndef RUBY_DUCKDB_BLOB_H
2
+ #define RUBY_DUCKDB_BLOB_H
3
+
4
+ /*
5
+ * blob is supported by duckdb v0.2.5 or later
6
+ */
7
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
8
+
9
+ void init_duckdb_blob(void);
10
+
11
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
12
+
13
+ #endif
14
+
data/ext/duckdb/duckdb.c CHANGED
@@ -12,4 +12,16 @@ Init_duckdb_native(void)
12
12
  init_duckdb_connection();
13
13
  init_duckdb_result();
14
14
  init_duckdb_prepared_statement();
15
+
16
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
17
+
18
+ init_duckdb_blob();
19
+
20
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
21
+
22
+ #ifdef HAVE_DUCKDB_APPENDER_CREATE
23
+
24
+ init_duckdb_appender();
25
+
26
+ #endif /* HAVE_DUCKDB_APPENDER_CREATE */
15
27
  }
@@ -2,5 +2,9 @@ require 'mkmf'
2
2
 
3
3
  dir_config('duckdb')
4
4
  if have_library('duckdb')
5
+ have_func('duckdb_value_blob', 'duckdb.h')
6
+ have_func('duckdb_bind_blob', 'duckdb.h')
7
+ have_func('duckdb_appender_create', 'duckdb.h')
8
+ have_func('duckdb_free', 'duckdb.h')
5
9
  create_makefile('duckdb/duckdb_native')
6
10
  end
@@ -70,7 +70,7 @@ static idx_t check_index(VALUE vidx)
70
70
  return idx;
71
71
  }
72
72
 
73
- static VALUE duckdb_prepared_statement_bind_boolean(VALUE self, VALUE vidx, VALUE val)
73
+ static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val)
74
74
  {
75
75
  rubyDuckDBPreparedStatement *ctx;
76
76
  idx_t idx = check_index(vidx);
@@ -86,6 +86,20 @@ static VALUE duckdb_prepared_statement_bind_boolean(VALUE self, VALUE vidx, VALU
86
86
  return self;
87
87
  }
88
88
 
89
+ static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val)
90
+ {
91
+ rubyDuckDBPreparedStatement *ctx;
92
+ idx_t idx = check_index(vidx);
93
+ int8_t i8val = (int8_t)NUM2INT(val);
94
+
95
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
96
+
97
+ if (duckdb_bind_int8(ctx->prepared_statement, idx, i8val) == DuckDBError) {
98
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
99
+ }
100
+ return self;
101
+ }
102
+
89
103
  static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val)
90
104
  {
91
105
  rubyDuckDBPreparedStatement *ctx;
@@ -168,6 +182,20 @@ static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALU
168
182
  return self;
169
183
  }
170
184
 
185
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
186
+ static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob)
187
+ {
188
+ rubyDuckDBPreparedStatement *ctx;
189
+ idx_t idx = check_index(vidx);
190
+
191
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
192
+ if (duckdb_bind_blob(ctx->prepared_statement, idx, (const void *)StringValuePtr(blob), (idx_t)RSTRING_LEN(blob)) == DuckDBError) {
193
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
194
+ }
195
+ return self;
196
+ }
197
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
198
+
171
199
  static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx)
172
200
  {
173
201
  rubyDuckDBPreparedStatement *ctx;
@@ -189,12 +217,16 @@ void init_duckdb_prepared_statement(void)
189
217
  rb_define_method(cDuckDBPreparedStatement, "initialize", duckdb_prepared_statement_initialize, 2);
190
218
  rb_define_method(cDuckDBPreparedStatement, "execute", duckdb_prepared_statement_execute, 0);
191
219
  rb_define_method(cDuckDBPreparedStatement, "nparams", duckdb_prepared_statement_nparams, 0);
192
- rb_define_method(cDuckDBPreparedStatement, "bind_boolean", duckdb_prepared_statement_bind_boolean, 2);
220
+ rb_define_method(cDuckDBPreparedStatement, "bind_bool", duckdb_prepared_statement_bind_bool, 2);
221
+ rb_define_method(cDuckDBPreparedStatement, "bind_int8", duckdb_prepared_statement_bind_int8, 2);
193
222
  rb_define_method(cDuckDBPreparedStatement, "bind_int16", duckdb_prepared_statement_bind_int16, 2);
194
223
  rb_define_method(cDuckDBPreparedStatement, "bind_int32", duckdb_prepared_statement_bind_int32, 2);
195
224
  rb_define_method(cDuckDBPreparedStatement, "bind_int64", duckdb_prepared_statement_bind_int64, 2);
196
225
  rb_define_method(cDuckDBPreparedStatement, "bind_float", duckdb_prepared_statement_bind_float, 2);
197
226
  rb_define_method(cDuckDBPreparedStatement, "bind_double", duckdb_prepared_statement_bind_double, 2);
198
227
  rb_define_method(cDuckDBPreparedStatement, "bind_varchar", duckdb_prepared_statement_bind_varchar, 2);
228
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
229
+ rb_define_method(cDuckDBPreparedStatement, "bind_blob", duckdb_prepared_statement_bind_blob, 2);
230
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
199
231
  rb_define_method(cDuckDBPreparedStatement, "bind_null", duckdb_prepared_statement_bind_null, 1);
200
232
  }
data/ext/duckdb/result.c CHANGED
@@ -52,6 +52,25 @@ static VALUE to_ruby_obj_double(duckdb_result *result, idx_t col_idx, idx_t row_
52
52
  return DBL2NUM(dval);
53
53
  }
54
54
 
55
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
56
+ static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx, idx_t row_idx)
57
+ {
58
+ VALUE str;
59
+ duckdb_blob bval = duckdb_value_blob(result, col_idx, row_idx);
60
+ str = rb_str_new(bval.data, bval.size);
61
+
62
+ if (bval.data) {
63
+ #ifdef HAVE_DUCKDB_FREE
64
+ duckdb_free(bval.data);
65
+ #else
66
+ free(bval.data);
67
+ #endif
68
+ }
69
+
70
+ return str;
71
+ }
72
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
73
+
55
74
  static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
56
75
  {
57
76
  char *p;
@@ -72,10 +91,23 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
72
91
  return to_ruby_obj_float(result, col_idx, row_idx);
73
92
  case DUCKDB_TYPE_DOUBLE:
74
93
  return to_ruby_obj_double(result, col_idx, row_idx);
94
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
95
+ case DUCKDB_TYPE_BLOB:
96
+ return to_ruby_obj_string_from_blob(result, col_idx, row_idx);
97
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
75
98
  default:
76
99
  p = duckdb_value_varchar(result, col_idx, row_idx);
77
- obj = rb_str_new2(p);
78
- free(p);
100
+ if (p) {
101
+ obj = rb_str_new2(p);
102
+ #ifdef HAVE_DUCKDB_FREE
103
+ duckdb_free(p);
104
+ #else
105
+ free(p);
106
+ #endif /* HAVE_DUCKDB_FREE */
107
+ if (result->columns[col_idx].type == DUCKDB_TYPE_HUGEINT) {
108
+ obj = rb_funcall(obj, rb_intern("to_i"), 0);
109
+ }
110
+ }
79
111
  }
80
112
  return obj;
81
113
  }
@@ -9,9 +9,28 @@
9
9
  #include "./result.h"
10
10
  #include "./prepared_statement.h"
11
11
 
12
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
13
+
14
+ #include "./blob.h"
15
+
16
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
17
+
18
+ #ifdef HAVE_DUCKDB_APPENDER_CREATE
19
+
20
+ #include "./appender.h"
21
+
22
+ #endif /* HAVE_DUCKDB_APPENDER_CREATE */
23
+
12
24
  extern VALUE mDuckDB;
13
25
  extern VALUE cDuckDBDatabase;
14
26
  extern VALUE cDuckDBConnection;
27
+
28
+ #ifdef HAVE_DUCKDB_VALUE_BLOB
29
+
30
+ extern VALUE cDuckDBBlob;
31
+
32
+ #endif /* HAVE_DUCKDB_VALUE_BLOB */
33
+
15
34
  extern VALUE eDuckDBError;
16
35
 
17
36
  #endif
data/lib/duckdb.rb CHANGED
@@ -4,6 +4,7 @@ require 'duckdb/database'
4
4
  require 'duckdb/connection'
5
5
  require 'duckdb/result'
6
6
  require 'duckdb/prepared_statement'
7
+ require 'duckdb/appender'
7
8
 
8
9
  # DuckDB provides Ruby interface of DuckDB.
9
10
  module DuckDB
@@ -0,0 +1,102 @@
1
+ require 'date'
2
+
3
+ module DuckDB
4
+ if defined?(DuckDB::Appender)
5
+ # The DuckDB::Appender encapsulates DuckDB Appender.
6
+ #
7
+ # require 'duckdb'
8
+ # db = DuckDB::Database.open
9
+ # con = db.connect
10
+ # con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
11
+ # appender = con.appender('users')
12
+ # appender.append_row(1, 'Alice')
13
+ #
14
+ class Appender
15
+ RANGE_INT16 = (-32_768..32_767).freeze
16
+ RANGE_INT32 = (-2_147_483_648..2_147_483_647).freeze
17
+ RANGE_INT64 = (-9_223_372_036_854_775_808..9_223_372_036_854_775_807).freeze
18
+
19
+ def append_hugeint(value)
20
+ case value
21
+ when Integer
22
+ append_varchar(value.to_s)
23
+ else
24
+ rb_raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
25
+ end
26
+ end
27
+
28
+ #
29
+ # appends value.
30
+ #
31
+ # require 'duckdb'
32
+ # db = DuckDB::Database.open
33
+ # con = db.connect
34
+ # con.query('CREATE TABLE users (id INTEGER, name VARCHAR)')
35
+ # appender = con.appender('users')
36
+ # appender.begin_row
37
+ # appender.append(1)
38
+ # appender.append('Alice')
39
+ # appender.end_row
40
+ #
41
+ def append(value)
42
+ case value
43
+ when NilClass
44
+ append_null
45
+ when Float
46
+ append_double(value)
47
+ when Integer
48
+ case value
49
+ when RANGE_INT16
50
+ append_int16(value)
51
+ when RANGE_INT32
52
+ append_int32(value)
53
+ when RANGE_INT64
54
+ append_int64(value)
55
+ else
56
+ append_hugeint(value)
57
+ end
58
+ when String
59
+ if defined?(DuckDB::Blob)
60
+ blob?(value) ? append_blob(value) : append_varchar(value)
61
+ else
62
+ append_varchar(value)
63
+ end
64
+ when TrueClass, FalseClass
65
+ append_bool(value)
66
+ when Time
67
+ append_varchar(value.strftime('%Y-%m-%d %H:%M:%S.%N'))
68
+ when Date
69
+ append_varchar(value.strftime('%Y-%m-%d'))
70
+ else
71
+ rb_raise(DuckDB::Error, "not supported type #{value} (value.class)")
72
+ end
73
+ end
74
+
75
+ #
76
+ # append a row.
77
+ #
78
+ # appender.append_row(1, 'Alice')
79
+ #
80
+ # is same as:
81
+ #
82
+ # appender.begin_row
83
+ # appender.append(1)
84
+ # appender.append('Alice')
85
+ # appender.end_row
86
+ #
87
+ def append_row(*args)
88
+ begin_row
89
+ args.each do |arg|
90
+ append(arg)
91
+ end
92
+ end_row
93
+ end
94
+
95
+ private
96
+
97
+ def blob?(value)
98
+ value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
99
+ end
100
+ end
101
+ end
102
+ end
@@ -44,6 +44,35 @@ module DuckDB
44
44
  end
45
45
  end
46
46
 
47
+ #
48
+ # returns PreparedStatement object.
49
+ # The first argument is SQL string.
50
+ #
51
+ def prepared_statement(str)
52
+ PreparedStatement.new(self, str)
53
+ end
54
+
55
+ #
56
+ # returns Appender object.
57
+ # The first argument is table name
58
+ #
59
+ def appender(table)
60
+ appender = create_appender(table)
61
+
62
+ return appender unless block_given?
63
+
64
+ yield appender
65
+ appender.flush
66
+ appender.close
67
+ end
68
+
69
+ private
70
+
71
+ def create_appender(table)
72
+ t1, t2 = table.split('.')
73
+ t2 ? Appender.new(self, t1, t2) : Appender.new(self, t2, t1)
74
+ end
75
+
47
76
  alias execute query
48
77
  alias open connect
49
78
  alias close disconnect
@@ -13,6 +13,19 @@ module DuckDB
13
13
  # stmt.execute
14
14
  class PreparedStatement
15
15
 
16
+ RANGE_INT16 = -32768..32767
17
+ RANGE_INT32 = -2147483648..2147483647
18
+ RANGE_INT64 = -9223372036854775808..9223372036854775807
19
+
20
+ def bind_hugeint(i, value)
21
+ case value
22
+ when Integer
23
+ bind_varchar(i, value.to_s)
24
+ else
25
+ rb_raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
26
+ end
27
+ end
28
+
16
29
  # binds i-th parameter with SQL prepared statement.
17
30
  # The first argument is index of parameter. The index of first parameter is
18
31
  # 1 not 0.
@@ -31,11 +44,20 @@ module DuckDB
31
44
  when Float
32
45
  bind_double(i, value)
33
46
  when Integer
34
- bind_int64(i, value)
47
+ case value
48
+ when RANGE_INT64
49
+ bind_int64(i, value)
50
+ else
51
+ bind_varchar(i, value.to_s)
52
+ end
35
53
  when String
36
- bind_varchar(i, value)
54
+ if defined?(DuckDB::Blob)
55
+ blob?(value) ? bind_blob(i, value) : bind_varchar(i, value)
56
+ else
57
+ bind_varchar(i, value)
58
+ end
37
59
  when TrueClass, FalseClass
38
- bind_boolean(i, value)
60
+ bind_bool(i, value)
39
61
  when Time
40
62
  bind_varchar(i, value.strftime('%Y-%m-%d %H:%M:%S.%N'))
41
63
  when Date
@@ -44,5 +66,11 @@ module DuckDB
44
66
  rb_raise(DuckDB::Error, "not supported type #{value} (value.class)")
45
67
  end
46
68
  end
69
+
70
+ private
71
+
72
+ def blob?(value)
73
+ value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
74
+ end
47
75
  end
48
76
  end
@@ -1,5 +1,5 @@
1
1
  module DuckDB
2
2
  # The version string of ruby-duckdb.
3
3
  # Currently, ruby-duckdb is NOT semantic versioning.
4
- VERSION = '0.0.10'.freeze
4
+ VERSION = '0.2.7.0'.freeze
5
5
  end
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.0.10
4
+ version: 0.2.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Suketa
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-07 00:00:00.000000000 Z
11
+ date: 2021-06-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -75,7 +75,9 @@ extensions:
75
75
  - ext/duckdb/extconf.rb
76
76
  extra_rdoc_files: []
77
77
  files:
78
- - ".github/workflows/test_by_github.yml"
78
+ - ".github/workflows/test_on_macos.yml"
79
+ - ".github/workflows/test_on_ubuntu.yml"
80
+ - ".github/workflows/test_on_windows.yml"
79
81
  - ".gitignore"
80
82
  - ".travis.yml"
81
83
  - CHANGELOG.md
@@ -87,6 +89,10 @@ files:
87
89
  - bin/console
88
90
  - bin/setup
89
91
  - duckdb.gemspec
92
+ - ext/duckdb/appender.c
93
+ - ext/duckdb/appender.h
94
+ - ext/duckdb/blob.c
95
+ - ext/duckdb/blob.h
90
96
  - ext/duckdb/connection.c
91
97
  - ext/duckdb/connection.h
92
98
  - ext/duckdb/database.c
@@ -101,6 +107,7 @@ files:
101
107
  - ext/duckdb/result.h
102
108
  - ext/duckdb/ruby-duckdb.h
103
109
  - lib/duckdb.rb
110
+ - lib/duckdb/appender.rb
104
111
  - lib/duckdb/connection.rb
105
112
  - lib/duckdb/database.rb
106
113
  - lib/duckdb/prepared_statement.rb
@@ -113,7 +120,7 @@ metadata:
113
120
  homepage_uri: https://github.com/suketa/ruby-duckdb
114
121
  source_code_uri: https://github.com/suketa/ruby-duckdb
115
122
  changelog_uri: https://github.com/suketa/ruby-duckdb/blob/master/CHANGELOG.md
116
- post_install_message:
123
+ post_install_message:
117
124
  rdoc_options: []
118
125
  require_paths:
119
126
  - lib
@@ -128,8 +135,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
135
  - !ruby/object:Gem::Version
129
136
  version: '0'
130
137
  requirements: []
131
- rubygems_version: 3.2.0.rc.2
132
- signing_key:
138
+ rubygems_version: 3.2.15
139
+ signing_key:
133
140
  specification_version: 4
134
141
  summary: This module is Ruby binding for DuckDB database engine.
135
142
  test_files: []
@@ -1,66 +0,0 @@
1
- name: Ubuntu
2
-
3
- on: [push]
4
-
5
- jobs:
6
- build:
7
-
8
- runs-on: ubuntu-latest
9
- strategy:
10
- matrix:
11
- ruby: ['2.5.8', '2.6.6', '2.7.2', 'head']
12
- duckdb: ['0.2.2', '0.2.1']
13
-
14
- steps:
15
- - uses: actions/checkout@v2
16
-
17
- - name: Set up Ruby
18
- uses: ruby/setup-ruby@v1
19
- with:
20
- ruby-version: ${{ matrix.ruby }}
21
-
22
- - name: duckdb 0.2.2 cache
23
- id: duckdb-cache-v0_2_2
24
- uses: actions/cache@v1.1.0
25
- with:
26
- path: duckdb-v0.2.2
27
- key: ${{ runner.os }}-duckdb-v0_2_2_001
28
- restore-keys: |
29
- ${{ runner.os }}-duckdb-v0_2_2
30
-
31
- - name: duckdb 0.2.1 cache
32
- id: duckdb-cache-v0_2_1
33
- uses: actions/cache@v1.1.0
34
- with:
35
- path: duckdb-v0.2.1
36
- key: ${{ runner.os }}-duckdb-v0_2_1_001
37
- restore-keys: |
38
- ${{ runner.os }}-duckdb-v0_2_1
39
-
40
- - name: Build duckdb 0.2.2
41
- if: steps.duckdb-cache-v0_2_2.outputs.cache-hit != 'true'
42
- run: |
43
- git clone -b v0.2.2 https://github.com/cwida/duckdb.git duckdb-tmp-v0.2.2
44
- cd duckdb-tmp-v0.2.2 && make && cd ..
45
- rm -rf duckdb-v0.2.2
46
- mkdir -p duckdb-v0.2.2/build/release/src duckdb-v0.2.2/src
47
- cp -rip duckdb-tmp-v0.2.2/build/release/src/*.so duckdb-v0.2.2/build/release/src
48
- cp -rip duckdb-tmp-v0.2.2/src/include duckdb-v0.2.2/src/
49
-
50
- - name: Build duckdb 0.2.1
51
- if: steps.duckdb-cache-v0_2_1.outputs.cache-hit != 'true'
52
- run: |
53
- git clone -b v0.2.1 https://github.com/cwida/duckdb.git duckdb-tmp-v0.2.1
54
- cd duckdb-tmp-v0.2.1 && make && cd ..
55
- rm -rf duckdb-v0.2.1
56
- mkdir -p duckdb-v0.2.1/build/release/src duckdb-v0.2.1/src
57
- cp -rip duckdb-tmp-v0.2.1/build/release/src/*.so duckdb-v0.2.1/build/release/src
58
- cp -rip duckdb-tmp-v0.2.1/src/include duckdb-v0.2.1/src/
59
-
60
- - name: Build and test with Rake with Ruby ${{ matrix.ruby }}
61
- env:
62
- DUCKDB_VERSION: ${{ matrix.duckdb }}
63
- run: |
64
- gem install bundler
65
- bundle install --jobs 4 --retry 3
66
- bundle exec rake -- --with-duckdb-include=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/src/include --with-duckdb-lib=${GITHUB_WORKSPACE}/duckdb-v${DUCKDB_VERSION}/build/release/src/