duckdb 0.0.5 → 0.0.6

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: 599ebecd3f693be06ff46fec535485d6ac6019cd889405a502d21a2f801c9ba8
4
- data.tar.gz: '0811911b5f0c3404f8c7ff9c2351d97668013dd576d4f5a98775e9af45df5e52'
3
+ metadata.gz: 74313dca99b11539431ecfe95cdd3f6392e0993776f292487991cf02e654f78f
4
+ data.tar.gz: 151e355bd98be14256b1e78e02eeb7c60dff12e1f2a7ef875e3e9604b7bfb2b3
5
5
  SHA512:
6
- metadata.gz: b4ca8e956de0edbb9aa9ceed9273a48f3cf847e5ff79732b849465c59fa2030af5cd81c62344e953e96990e11c48ff1b2dd8bd3cd87f3bc8271079aeb69a31bd
7
- data.tar.gz: 3501865c8c0aa7c70761705e06026aadd95e112d34fd9eed1152ae269407fddc7cdbe6a84f6f3f8cda917022bda45fb0d349b51400b939f43b74ae64bb8e43bf
6
+ metadata.gz: 6da56e491796d920c3c330d5dd2941b6b23f119ebb0bfed4f8e5ae25e2d2f1a83445cd06cd9d0dfab55a19184b9ed6302f04d2f61c038c8352fec8c0ebc60372
7
+ data.tar.gz: 8e6f30d324473da40e4e65c7ec8d6a96625eefa835647d8412cc8a8755b5cc29246100ddb2f48f42cc60f006927af4d8b1373b2c1c3e2e6c98f2f891d83fa8e4
@@ -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.x', '2.6.x']
12
+ duckdb: ['0.1.2', '0.1.3']
13
+
14
+ steps:
15
+ - uses: actions/checkout@v1
16
+
17
+ - name: Set up Ruby
18
+ uses: actions/setup-ruby@v1
19
+ with:
20
+ ruby-version: ${{ matrix.ruby }}
21
+
22
+ - name: duckdb 0.1.2 cache
23
+ id: duckdb-cache-v0_1_2
24
+ uses: actions/cache@v1.1.0
25
+ with:
26
+ path: duckdb-v0.1.2
27
+ key: ${{ runner.os }}-duckdb-v0_1_2_007
28
+ restore-keys: |
29
+ ${{ runner.os }}-duckdb-v0_1_2
30
+
31
+ - name: Build duckdb 0.1.2
32
+ if: steps.duckdb-cache-v0_1_2.outputs.cache-hit != 'true'
33
+ run: |
34
+ git clone -b v0.1.2 https://github.com/cwida/duckdb.git duckdb-tmp-v0.1.2
35
+ cd duckdb-tmp-v0.1.2 && make && cd ..
36
+ rm -rf duckdb-v0.1.2
37
+ mkdir -p duckdb-v0.1.2/build/release/src duckdb-v0.1.2/src
38
+ cp -rip duckdb-tmp-v0.1.2/build/release/src/*.so duckdb-v0.1.2/build/release/src
39
+ cp -rip duckdb-tmp-v0.1.2/src/include duckdb-v0.1.2/src/
40
+
41
+ - name: duckdb 0.1.3 cache
42
+ id: duckdb-cache-v0_1_3
43
+ uses: actions/cache@v1.1.0
44
+ with:
45
+ path: duckdb-v0.1.3
46
+ key: ${{ runner.os }}-duckdb-v0_1_3_001
47
+ restore-keys: |
48
+ ${{ runner.os }}-duckdb-v0_1_3
49
+
50
+ - name: Build duckdb 0.1.3
51
+ if: steps.duckdb-cache-v0_1_3.outputs.cache-hit != 'true'
52
+ run: |
53
+ git clone -b v0.1.3 https://github.com/cwida/duckdb.git duckdb-tmp-v0.1.3
54
+ cd duckdb-tmp-v0.1.3 && make && cd ..
55
+ rm -rf duckdb-v0.1.3
56
+ mkdir -p duckdb-v0.1.3/build/release/src duckdb-v0.1.3/src
57
+ cp -rip duckdb-tmp-v0.1.3/build/release/src/*.so duckdb-v0.1.3/build/release/src
58
+ cp -rip duckdb-tmp-v0.1.3/src/include duckdb-v0.1.3/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/
data/.travis.yml ADDED
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+ cache:
3
+ bundler: true
4
+ directories:
5
+ - ${HOME}/duckdb-v0.1.2
6
+ - ${HOME}/duckdb-v0.1.3
7
+ before_install:
8
+ - yes | gem update --system
9
+ - if [[ ! -d ${HOME}/duckdb-v0.1.2/build ]]; then cd ${HOME} && git clone -b v0.1.2 https://github.com/cwida/duckdb.git duckdb-v0.1.2 && cd duckdb-v0.1.2 && make && cd ${TRAVIS_BUILD_DIR}; fi
10
+ - if [[ ! -d ${HOME}/duckdb-v0.1.3/build ]]; then cd ${HOME} && git clone -b v0.1.3 https://github.com/cwida/duckdb.git duckdb-v0.1.3 && cd duckdb-v0.1.3 && make && cd ${TRAVIS_BUILD_DIR}; fi
11
+
12
+ env:
13
+ - DUCKDB_VERSION=0.1.2
14
+ - DUCKDB_VERSION=0.1.3
15
+ rvm:
16
+ - 2.5.7
17
+ - 2.6.5
18
+ - 2.7.0
19
+ - ruby-head
20
+ 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,5 +1,13 @@
1
1
  # ChangeLog
2
2
 
3
+ ## 0.0.6
4
+
5
+ - add alias `execute` of `DuckDB::Connection#query`
6
+ - support `duckdb version 0.1.3`
7
+ - add `DuckDB:PreparedStatement`
8
+ - create CI (GitHub Actions / Travis-CI)
9
+ - create database only once in result_test.rb
10
+
3
11
  ## 0.0.5
4
12
 
5
13
  - add `DuckDB::Error`
data/Gemfile.lock CHANGED
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (0.0.5)
4
+ duckdb (0.0.6)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  minitest (5.13.0)
10
- rake (10.5.0)
11
- rake-compiler (1.0.8)
10
+ rake (13.0.1)
11
+ rake-compiler (1.1.0)
12
12
  rake
13
13
 
14
14
  PLATFORMS
@@ -18,8 +18,8 @@ DEPENDENCIES
18
18
  bundler (~> 2.0)
19
19
  duckdb!
20
20
  minitest (~> 5.0)
21
- rake (~> 10.0)
21
+ rake (~> 13.0)
22
22
  rake-compiler
23
23
 
24
24
  BUNDLED WITH
25
- 2.0.2
25
+ 2.1.4
data/README.md CHANGED
@@ -1,5 +1,7 @@
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
+ [![](https://github.com/suketa/ruby-duckdb/workflows/Ubuntu/badge.svg)](https://github.com/suketa/ruby-duckdb/actions?query=workflow%3AUbuntu)
3
5
 
4
6
  ## Description
5
7
 
data/duckdb.gemspec CHANGED
@@ -26,7 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.extensions = ["ext/duckdb/extconf.rb"]
27
27
 
28
28
  spec.add_development_dependency "bundler", "~> 2.0"
29
- spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rake", "~> 13.0"
30
30
  spec.add_development_dependency "rake-compiler"
31
31
  spec.add_development_dependency "minitest", "~> 5.0"
32
32
  end
@@ -1,7 +1,5 @@
1
1
  #include "ruby-duckdb.h"
2
2
 
3
- static VALUE cDuckDBConnection;
4
-
5
3
  static void deallocate(void *ctx)
6
4
  {
7
5
  rubyDuckDBConnection *p = (rubyDuckDBConnection *)ctx;
@@ -16,7 +14,8 @@ static VALUE allocate(VALUE klass)
16
14
  return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
17
15
  }
18
16
 
19
- VALUE create_connection(VALUE oDuckDBDatabase) {
17
+ VALUE create_connection(VALUE oDuckDBDatabase)
18
+ {
20
19
  rubyDuckDB *ctxdb;
21
20
  rubyDuckDBConnection *ctxcon;
22
21
  VALUE obj;
@@ -34,8 +33,8 @@ VALUE create_connection(VALUE oDuckDBDatabase) {
34
33
  return obj;
35
34
  }
36
35
 
37
- static VALUE duckdb_connection_query(VALUE self, VALUE str) {
38
-
36
+ static VALUE duckdb_connection_query_sql(VALUE self, VALUE str)
37
+ {
39
38
  rubyDuckDBConnection *ctx;
40
39
  rubyDuckDBResult *ctxr;
41
40
 
@@ -55,5 +54,5 @@ void init_duckdb_connection(void)
55
54
  cDuckDBConnection = rb_define_class_under(mDuckDB, "Connection", rb_cObject);
56
55
  rb_define_alloc_func(cDuckDBConnection, allocate);
57
56
 
58
- rb_define_method(cDuckDBConnection, "query", duckdb_connection_query, 1);
57
+ rb_define_private_method(cDuckDBConnection, "query_sql", duckdb_connection_query_sql, 1);
59
58
  }
@@ -7,6 +7,8 @@ struct _rubyDuckDBConnection {
7
7
 
8
8
  typedef struct _rubyDuckDBConnection rubyDuckDBConnection;
9
9
 
10
+ VALUE cDuckDBConnection;
11
+
10
12
  void init_duckdb_connection(void);
11
13
  VALUE create_connection(VALUE oDuckDBDatabase);
12
14
 
@@ -36,11 +36,13 @@ static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase
36
36
  return obj;
37
37
  }
38
38
 
39
- static VALUE duckdb_database_connect(VALUE self) {
39
+ static VALUE duckdb_database_connect(VALUE self)
40
+ {
40
41
  return create_connection(self);
41
42
  }
42
43
 
43
- void init_duckdb_database(void) {
44
+ void init_duckdb_database(void)
45
+ {
44
46
  VALUE cDuckDBDatabase = rb_define_class_under(mDuckDB, "Database", rb_cObject);
45
47
  rb_define_alloc_func(cDuckDBDatabase, allocate);
46
48
  rb_define_singleton_method(cDuckDBDatabase, "open", duckdb_database_s_open, -1);
data/ext/duckdb/duckdb.c CHANGED
@@ -3,11 +3,13 @@
3
3
  VALUE mDuckDB;
4
4
 
5
5
  void
6
- Init_duckdb_native(void) {
6
+ Init_duckdb_native(void)
7
+ {
7
8
  mDuckDB = rb_define_module("DuckDB");
8
9
 
9
10
  init_duckdb_error();
10
11
  init_duckdb_database();
11
12
  init_duckdb_connection();
12
13
  init_duckdb_result();
14
+ init_duckdb_prepared_statement();
13
15
  }
data/ext/duckdb/error.c CHANGED
@@ -1,5 +1,6 @@
1
1
  #include "ruby-duckdb.h"
2
2
 
3
- void init_duckdb_error(void) {
3
+ void init_duckdb_error(void)
4
+ {
4
5
  eDuckDBError = rb_define_class_under(mDuckDB, "Error", rb_eStandardError);
5
6
  }
@@ -1,5 +1,7 @@
1
1
  require 'mkmf'
2
2
 
3
3
  dir_config('duckdb')
4
- have_library('duckdb')
5
- create_makefile('duckdb/duckdb_native')
4
+ if have_library('duckdb')
5
+ have_func('duckdb_bind_null', 'duckdb.h')
6
+ create_makefile('duckdb/duckdb_native')
7
+ end
@@ -0,0 +1,205 @@
1
+ #include "ruby-duckdb.h"
2
+
3
+ static VALUE cDuckDBPreparedStatement;
4
+
5
+ static void deallocate(void *ctx)
6
+ {
7
+ rubyDuckDBPreparedStatement *p = (rubyDuckDBPreparedStatement *)ctx;
8
+
9
+ duckdb_destroy_prepare(&(p->prepared_statement));
10
+ xfree(p);
11
+ }
12
+
13
+ static VALUE allocate(VALUE klass)
14
+ {
15
+ rubyDuckDBPreparedStatement *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBPreparedStatement));
16
+ return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
17
+ }
18
+
19
+ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query)
20
+ {
21
+ rubyDuckDBConnection *ctxcon;
22
+ rubyDuckDBPreparedStatement *ctx;
23
+
24
+ if (!rb_obj_is_kind_of(con, cDuckDBConnection)) {
25
+ rb_raise(rb_eTypeError, "1st argument should be instance of DackDB::Connection");
26
+ }
27
+
28
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
29
+ Data_Get_Struct(con, rubyDuckDBConnection, ctxcon);
30
+
31
+ if (duckdb_prepare(ctxcon->con, StringValuePtr(query), &(ctx->prepared_statement)) == DuckDBError) {
32
+ /* TODO: include query parameter information in error message. */
33
+ rb_raise(eDuckDBError, "failed to prepare statement");
34
+ }
35
+ return self;
36
+ }
37
+
38
+ static VALUE duckdb_prepared_statement_nparams(VALUE self)
39
+ {
40
+ rubyDuckDBPreparedStatement *ctx;
41
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
42
+
43
+ if (duckdb_nparams(ctx->prepared_statement, &(ctx->nparams)) == DuckDBError) {
44
+ rb_raise(eDuckDBError, "failed to get number of parameters");
45
+ }
46
+ return rb_int2big(ctx->nparams);
47
+ }
48
+
49
+
50
+ static VALUE duckdb_prepared_statement_execute(VALUE self)
51
+ {
52
+ rubyDuckDBPreparedStatement *ctx;
53
+ rubyDuckDBResult *ctxr;
54
+ VALUE result = create_result();
55
+
56
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
57
+ Data_Get_Struct(result, rubyDuckDBResult, ctxr);
58
+ if (duckdb_execute_prepared(ctx->prepared_statement, &(ctxr->result)) == DuckDBError) {
59
+ rb_raise(eDuckDBError, "%s", ctxr->result.error_message);
60
+ }
61
+ return result;
62
+ }
63
+
64
+ static index_t check_index(VALUE vidx)
65
+ {
66
+ index_t idx = FIX2INT(vidx);
67
+ if (idx <= 0) {
68
+ rb_raise(rb_eArgError, "index of parameter must be greater than 0");
69
+ }
70
+ return idx;
71
+ }
72
+
73
+ static VALUE duckdb_prepared_statement_bind_boolean(VALUE self, VALUE vidx, VALUE val)
74
+ {
75
+ rubyDuckDBPreparedStatement *ctx;
76
+ index_t idx = check_index(vidx);
77
+
78
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
79
+ if (val != Qtrue && val != Qfalse) {
80
+ rb_raise(rb_eArgError, "binding value must be boolean");
81
+ }
82
+
83
+ if (duckdb_bind_boolean(ctx->prepared_statement, idx, (val == Qtrue)) == DuckDBError) {
84
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
85
+ }
86
+ return self;
87
+ }
88
+
89
+ static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val)
90
+ {
91
+ rubyDuckDBPreparedStatement *ctx;
92
+ index_t idx = check_index(vidx);
93
+ int16_t i16val = NUM2INT(val);
94
+
95
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
96
+
97
+ if (duckdb_bind_int16(ctx->prepared_statement, idx, i16val) == DuckDBError) {
98
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
99
+ }
100
+ return self;
101
+ }
102
+
103
+ static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE val)
104
+ {
105
+ rubyDuckDBPreparedStatement *ctx;
106
+ index_t idx = check_index(vidx);
107
+ int32_t i32val = NUM2LONG(val);
108
+
109
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
110
+
111
+ if (duckdb_bind_int32(ctx->prepared_statement, idx, i32val) == DuckDBError) {
112
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
113
+ }
114
+ return self;
115
+ }
116
+
117
+ static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE val)
118
+ {
119
+ rubyDuckDBPreparedStatement *ctx;
120
+ index_t idx = check_index(vidx);
121
+ int64_t i64val = NUM2LL(val);
122
+
123
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
124
+
125
+ if (duckdb_bind_int64(ctx->prepared_statement, idx, i64val) == DuckDBError) {
126
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
127
+ }
128
+ return self;
129
+ }
130
+
131
+ static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE val)
132
+ {
133
+ rubyDuckDBPreparedStatement *ctx;
134
+ index_t idx = check_index(vidx);
135
+ double dbl = NUM2DBL(val);
136
+
137
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
138
+
139
+ if (duckdb_bind_float(ctx->prepared_statement, idx, (float)dbl) == DuckDBError) {
140
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
141
+ }
142
+ return self;
143
+ }
144
+
145
+ static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE val)
146
+ {
147
+ rubyDuckDBPreparedStatement *ctx;
148
+ index_t idx = check_index(vidx);
149
+ double dbl = NUM2DBL(val);
150
+
151
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
152
+
153
+ if (duckdb_bind_double(ctx->prepared_statement, idx, dbl) == DuckDBError) {
154
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
155
+ }
156
+ return self;
157
+ }
158
+
159
+ static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str)
160
+ {
161
+ rubyDuckDBPreparedStatement *ctx;
162
+ index_t idx = check_index(vidx);
163
+
164
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
165
+ if (duckdb_bind_varchar(ctx->prepared_statement, idx, StringValuePtr(str)) == DuckDBError) {
166
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
167
+ }
168
+ return self;
169
+ }
170
+
171
+ #ifdef HAVE_DUCKDB_BIND_NULL
172
+ static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx)
173
+ {
174
+ rubyDuckDBPreparedStatement *ctx;
175
+ index_t idx = check_index(vidx);
176
+
177
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
178
+ if (duckdb_bind_null(ctx->prepared_statement, idx) == DuckDBError) {
179
+ rb_raise(eDuckDBError, "fail to bind %ld parameter", idx);
180
+ }
181
+ return self;
182
+ }
183
+ #endif
184
+
185
+ void init_duckdb_prepared_statement(void)
186
+ {
187
+ cDuckDBPreparedStatement = rb_define_class_under(mDuckDB, "PreparedStatement", rb_cObject);
188
+
189
+ rb_define_alloc_func(cDuckDBPreparedStatement, allocate);
190
+
191
+ rb_define_method(cDuckDBPreparedStatement, "initialize", duckdb_prepared_statement_initialize, 2);
192
+ rb_define_method(cDuckDBPreparedStatement, "execute", duckdb_prepared_statement_execute, 0);
193
+ rb_define_method(cDuckDBPreparedStatement, "nparams", duckdb_prepared_statement_nparams, 0);
194
+ rb_define_method(cDuckDBPreparedStatement, "bind_boolean", duckdb_prepared_statement_bind_boolean, 2);
195
+ rb_define_method(cDuckDBPreparedStatement, "bind_int16", duckdb_prepared_statement_bind_int16, 2);
196
+ rb_define_method(cDuckDBPreparedStatement, "bind_int32", duckdb_prepared_statement_bind_int32, 2);
197
+ rb_define_method(cDuckDBPreparedStatement, "bind_int64", duckdb_prepared_statement_bind_int64, 2);
198
+ rb_define_method(cDuckDBPreparedStatement, "bind_float", duckdb_prepared_statement_bind_float, 2);
199
+ rb_define_method(cDuckDBPreparedStatement, "bind_double", duckdb_prepared_statement_bind_double, 2);
200
+ rb_define_method(cDuckDBPreparedStatement, "bind_varchar", duckdb_prepared_statement_bind_varchar, 2);
201
+ #ifdef HAVE_DUCKDB_BIND_NULL
202
+ /* duckdb version > 0.1.1 */
203
+ rb_define_method(cDuckDBPreparedStatement, "bind_null", duckdb_prepared_statement_bind_null, 1);
204
+ #endif
205
+ }
@@ -0,0 +1,13 @@
1
+ #ifndef RUBY_DUCKDB_PREPARED_STATEMENT_H
2
+ #define RUBY_DUCKDB_PREPARED_STATEMENT_H
3
+
4
+ struct _rubyDuckDBPreparedStatement {
5
+ duckdb_prepared_statement prepared_statement;
6
+ index_t nparams;
7
+ };
8
+
9
+ typedef struct _rubyDuckDBPreparedStatement rubyDuckDBPreparedStatement;
10
+
11
+ void init_duckdb_prepared_statement(void);
12
+
13
+ #endif
data/ext/duckdb/result.c CHANGED
@@ -16,37 +16,44 @@ static VALUE allocate(VALUE klass)
16
16
  return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
17
17
  }
18
18
 
19
- static VALUE to_ruby_obj_boolean(duckdb_result *result, size_t col_idx, size_t row_idx) {
19
+ static VALUE to_ruby_obj_boolean(duckdb_result *result, index_t col_idx, index_t row_idx)
20
+ {
20
21
  bool bval = duckdb_value_boolean(result, col_idx, row_idx);
21
22
  return bval ? Qtrue : Qnil;
22
23
  }
23
24
 
24
- static VALUE to_ruby_obj_smallint(duckdb_result *result, size_t col_idx, size_t row_idx) {
25
+ static VALUE to_ruby_obj_smallint(duckdb_result *result, index_t col_idx, index_t row_idx)
26
+ {
25
27
  int16_t i16val = duckdb_value_int16(result, col_idx, row_idx);
26
28
  return INT2FIX(i16val);
27
29
  }
28
30
 
29
- static VALUE to_ruby_obj_integer(duckdb_result *result, size_t col_idx, size_t row_idx) {
31
+ static VALUE to_ruby_obj_integer(duckdb_result *result, index_t col_idx, index_t row_idx)
32
+ {
30
33
  int32_t i32val = duckdb_value_int32(result, col_idx, row_idx);
31
34
  return INT2NUM(i32val);
32
35
  }
33
36
 
34
- static VALUE to_ruby_obj_bigint(duckdb_result *result, size_t col_idx, size_t row_idx) {
37
+ static VALUE to_ruby_obj_bigint(duckdb_result *result, index_t col_idx, index_t row_idx)
38
+ {
35
39
  int64_t i64val = duckdb_value_int64(result, col_idx, row_idx);
36
40
  return rb_int2big(i64val);
37
41
  }
38
42
 
39
- static VALUE to_ruby_obj_float(duckdb_result *result, size_t col_idx, size_t row_idx) {
43
+ static VALUE to_ruby_obj_float(duckdb_result *result, index_t col_idx, index_t row_idx)
44
+ {
40
45
  float fval = duckdb_value_float(result, col_idx, row_idx);
41
46
  return DBL2NUM(fval);
42
47
  }
43
48
 
44
- static VALUE to_ruby_obj_double(duckdb_result *result, size_t col_idx, size_t row_idx) {
49
+ static VALUE to_ruby_obj_double(duckdb_result *result, index_t col_idx, index_t row_idx)
50
+ {
45
51
  double dval = duckdb_value_double(result, col_idx, row_idx);
46
52
  return DBL2NUM(dval);
47
53
  }
48
54
 
49
- static VALUE to_ruby_obj(duckdb_result *result, size_t col_idx, size_t row_idx) {
55
+ static VALUE to_ruby_obj(duckdb_result *result, index_t col_idx, index_t row_idx)
56
+ {
50
57
  char *p;
51
58
  VALUE obj = Qnil;
52
59
  if (result->columns[col_idx].nullmask[row_idx]) {
@@ -73,8 +80,9 @@ static VALUE to_ruby_obj(duckdb_result *result, size_t col_idx, size_t row_idx)
73
80
  return obj;
74
81
  }
75
82
 
76
- static VALUE row_array(rubyDuckDBResult *ctx, size_t row_idx) {
77
- size_t col_idx;
83
+ static VALUE row_array(rubyDuckDBResult *ctx, index_t row_idx)
84
+ {
85
+ index_t col_idx;
78
86
  VALUE ary = rb_ary_new2(ctx->result.column_count);
79
87
  for(col_idx = 0; col_idx < ctx->result.column_count; col_idx++) {
80
88
  rb_ary_store(ary, col_idx, to_ruby_obj(&(ctx->result), col_idx, row_idx));
@@ -82,16 +90,18 @@ static VALUE row_array(rubyDuckDBResult *ctx, size_t row_idx) {
82
90
  return ary;
83
91
  }
84
92
 
85
- static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj) {
93
+ static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj)
94
+ {
86
95
  rubyDuckDBResult *ctx;
87
96
  Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
88
97
 
89
98
  return LONG2FIX(ctx->result.row_count);
90
99
  }
91
100
 
92
- static VALUE duckdb_result_each(VALUE oDuckDBResult) {
101
+ static VALUE duckdb_result_each(VALUE oDuckDBResult)
102
+ {
93
103
  rubyDuckDBResult *ctx;
94
- size_t row_idx = 0;
104
+ index_t row_idx = 0;
95
105
 
96
106
  RETURN_SIZED_ENUMERATOR(oDuckDBResult, 0, 0, duckdb_result_row_size);
97
107
 
@@ -102,7 +112,8 @@ static VALUE duckdb_result_each(VALUE oDuckDBResult) {
102
112
  return oDuckDBResult;
103
113
  }
104
114
 
105
- VALUE create_result(void) {
115
+ VALUE create_result(void)
116
+ {
106
117
  return allocate(cDuckDBResult);
107
118
  }
108
119
 
@@ -7,6 +7,7 @@
7
7
  #include "./database.h"
8
8
  #include "./connection.h"
9
9
  #include "./result.h"
10
+ #include "./prepared_statement.h"
10
11
 
11
12
  extern VALUE mDuckDB;
12
13
 
data/lib/duckdb.rb CHANGED
@@ -1,6 +1,10 @@
1
1
  require 'duckdb/version'
2
+ require 'duckdb/database'
3
+ require 'duckdb/connection'
2
4
  require 'duckdb/duckdb_native'
3
5
  require 'duckdb/result'
6
+ require 'duckdb/prepared_statement'
4
7
 
8
+ # DuckDB provides Ruby interface of DuckDB.
5
9
  module DuckDB
6
10
  end
@@ -0,0 +1,34 @@
1
+ module DuckDB
2
+ # The DuckDB::Connection encapsulates connection with DuckDB database.
3
+ #
4
+ # require 'duckdb'
5
+ # db = DuckDB::Database.open
6
+ # con = db.connect
7
+ # con.query(sql)
8
+ class Connection
9
+ #
10
+ # executes sql with args.
11
+ # The first argument sql must be SQL string.
12
+ # The rest arguments are parameters of SQL string.
13
+ # The parameters must be '?' in SQL statement.
14
+ #
15
+ # require 'duckdb'
16
+ # db = DuckDB::Database.open('duckdb_file')
17
+ # con = db.connect
18
+ # users = con.query('SELECT * FROM users')
19
+ # sql = 'SELECT * FROM users WHERE name = ? AND email = ?'
20
+ # dave = con.query(sql, 'Dave', 'dave@example.com')
21
+ #
22
+ def query(sql, *args)
23
+ return query_sql(sql) if args.empty?
24
+
25
+ stmt = PreparedStatement.new(self, sql)
26
+ args.each_with_index do |arg, i|
27
+ stmt.bind(i + 1, arg)
28
+ end
29
+ stmt.execute
30
+ end
31
+
32
+ alias execute query
33
+ end
34
+ end
@@ -0,0 +1,24 @@
1
+ module DuckDB
2
+ # The Database class encapsulates a DuckDB database.
3
+ #
4
+ # The usage is as follows:
5
+ #
6
+ # require 'duckdb'
7
+ #
8
+ # db = DuckDB::Database.open # database in memory
9
+ # con = db.connect
10
+ #
11
+ # con.query('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
12
+ #
13
+ # con.query("INSERT into users VALUES(1, 'Alice')")
14
+ # con.query("INSERT into users VALUES(2, 'Bob')")
15
+ # con.query("INSERT into users VALUES(3, 'Cathy')")
16
+ #
17
+ # result = con.query('SELECT * from users')
18
+ # result.each do |row|
19
+ # p row
20
+ # end
21
+ #
22
+ class Database
23
+ end
24
+ end
@@ -0,0 +1,48 @@
1
+ require 'date'
2
+
3
+ module DuckDB
4
+ # The DuckDB::PreparedStatement encapsulates connection with DuckDB prepared
5
+ # statement.
6
+ #
7
+ # require 'duckdb'
8
+ # db = DuckDB::Database.open('duckdb_database')
9
+ # con = db.connect
10
+ # sql ='SELECT name, email FROM users WHERE email = ?'
11
+ # stmt = PreparedStatement.new(con, sql)
12
+ # stmt.bind(1, 'email@example.com')
13
+ # stmt.execute
14
+ class PreparedStatement
15
+
16
+ # binds i-th parameter with SQL prepared statement.
17
+ # The first argument is index of parameter. The index of first parameter is
18
+ # 1 not 0.
19
+ # The second argument value is the value of prepared statement parameter.
20
+ #
21
+ # require 'duckdb'
22
+ # db = DuckDB::Database.open('duckdb_database')
23
+ # con = db.connect
24
+ # sql ='SELECT name, email FROM users WHERE email = ?'
25
+ # stmt = PreparedStatement.new(con, sql)
26
+ # stmt.bind(1, 'email@example.com')
27
+ def bind(i, value)
28
+ case value
29
+ when NilClass
30
+ respond_to?(:bind_null) ? bind_null(i) : rb_raise(DuckDB::Error, 'This bind method does not support nil value. Re-compile ruby-duckdb with DuckDB version >= 0.1.1')
31
+ when Float
32
+ bind_double(i, value)
33
+ when Integer
34
+ bind_int64(i, value)
35
+ when String
36
+ bind_varchar(i, value)
37
+ when TrueClass, FalseClass
38
+ bind_boolean(i, value)
39
+ when Time
40
+ bind_varchar(i, value.strftime('%Y-%m-%d %H:%M:%S.%N'))
41
+ when Date
42
+ bind_varchar(i, value.strftime('%Y-%m-%d'))
43
+ else
44
+ rb_raise(DuckDB::Error, "not supported type #{value} (value.class)")
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/duckdb/result.rb CHANGED
@@ -1,4 +1,23 @@
1
1
  module DuckDB
2
+ # The Result class encapsulates a execute result of DuckDB database.
3
+ #
4
+ # The usage is as follows:
5
+ #
6
+ # require 'duckdb'
7
+ #
8
+ # db = DuckDB::Database.open # database in memory
9
+ # con = db.connect
10
+ #
11
+ # con.execute('CREATE TABLE users (id INTEGER, name VARCHAR(30))')
12
+ #
13
+ # con.execute("INSERT into users VALUES(1, 'Alice')")
14
+ # con.execute("INSERT into users VALUES(2, 'Bob')")
15
+ # con.execute("INSERT into users VALUES(3, 'Cathy')")
16
+ #
17
+ # result = con.execute('SELECT * from users')
18
+ # result.each do |row|
19
+ # p row
20
+ # end
2
21
  class Result
3
22
  include Enumerable
4
23
  end
@@ -1,3 +1,5 @@
1
1
  module DuckDB
2
- VERSION = '0.0.5'.freeze
2
+ # The version string of ruby-duckdb.
3
+ # Currently, ruby-duckdb is NOT semantic versioning.
4
+ VERSION = '0.0.6'.freeze
3
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.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Masaki Suketa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-04 00:00:00.000000000 Z
11
+ date: 2020-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake-compiler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -75,14 +75,15 @@ extensions:
75
75
  - ext/duckdb/extconf.rb
76
76
  extra_rdoc_files: []
77
77
  files:
78
+ - ".github/workflows/test_by_github.yml"
78
79
  - ".gitignore"
80
+ - ".travis.yml"
79
81
  - CHANGELOG.md
80
82
  - Gemfile
81
83
  - Gemfile.lock
82
84
  - LICENSE
83
85
  - README.md
84
86
  - Rakefile
85
- - TODO
86
87
  - bin/console
87
88
  - bin/setup
88
89
  - duckdb.gemspec
@@ -94,10 +95,15 @@ files:
94
95
  - ext/duckdb/error.c
95
96
  - ext/duckdb/error.h
96
97
  - ext/duckdb/extconf.rb
98
+ - ext/duckdb/prepared_statement.c
99
+ - ext/duckdb/prepared_statement.h
97
100
  - ext/duckdb/result.c
98
101
  - ext/duckdb/result.h
99
102
  - ext/duckdb/ruby-duckdb.h
100
103
  - lib/duckdb.rb
104
+ - lib/duckdb/connection.rb
105
+ - lib/duckdb/database.rb
106
+ - lib/duckdb/prepared_statement.rb
101
107
  - lib/duckdb/result.rb
102
108
  - lib/duckdb/version.rb
103
109
  homepage: https://github.com/suketa/ruby-duckdb
@@ -122,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
128
  - !ruby/object:Gem::Version
123
129
  version: '0'
124
130
  requirements: []
125
- rubygems_version: 3.0.3
131
+ rubygems_version: 3.1.2
126
132
  signing_key:
127
133
  specification_version: 4
128
134
  summary: This module is Ruby binding for DuckDB database engine.
data/TODO DELETED
@@ -1,2 +0,0 @@
1
- - add test
2
- - support prepared statement