duckdb 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +2 -2
- data/.github/workflows/test_on_ubuntu.yml +2 -2
- data/.github/workflows/test_on_windows.yml +1 -1
- data/CHANGELOG.md +8 -0
- data/Dockerfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +11 -0
- data/ext/duckdb/extconf.rb +2 -0
- data/ext/duckdb/prepared_statement.c +49 -0
- data/lib/duckdb/connection.rb +12 -5
- data/lib/duckdb/prepared_statement.rb +32 -12
- data/lib/duckdb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2948812978266d6ca2040d2071479f0484fe39719be860282e238b1e786a53e7
|
4
|
+
data.tar.gz: 3a3d10a5dd8e318b7a6274e6e32f0fc4850eeafada95673b42ed6c6121a36af5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f4bf27bf6c3e378650584e9226bd0c2e16a76a2d5e68c96451f5abafb4dfe6fbb4df705ceb754ac8df30ed36bc6fe67299f61861fa882ef11acac79dea1e80cf
|
7
|
+
data.tar.gz: 71f42787f8368ab322c5d8c9a9a74227117dbf0454601d9ac3ec407188497c34e437fd5de14bec2038d6f3df3233098b580a8e116f8590dedd8004b7ba934f5a
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: macos-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-
|
19
|
-
duckdb: ['0.9.
|
18
|
+
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-preview2', 'head']
|
19
|
+
duckdb: ['0.9.1', '0.8.1']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
@@ -15,8 +15,8 @@ jobs:
|
|
15
15
|
runs-on: ubuntu-latest
|
16
16
|
strategy:
|
17
17
|
matrix:
|
18
|
-
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-
|
19
|
-
duckdb: ['0.9.
|
18
|
+
ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-preview2', 'head']
|
19
|
+
duckdb: ['0.9.1', '0.8.1']
|
20
20
|
|
21
21
|
steps:
|
22
22
|
- uses: actions/checkout@v3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# ChangeLog
|
2
2
|
|
3
|
+
# 0.9.1
|
4
|
+
- add `DuckDB::PreparedStatement#parameter_name`.
|
5
|
+
- bump duckdb to 0.9.1.
|
6
|
+
|
7
|
+
# 0.9.0.1
|
8
|
+
- add `DuckDB::PreparedStatement#bind_parameter_index`.
|
9
|
+
- DuckDB::Connection#query accepts SQL with named bind parameters.
|
10
|
+
|
3
11
|
# 0.9.0
|
4
12
|
- bump duckdb to 0.9.0.
|
5
13
|
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -94,6 +94,17 @@ DuckDB::Database.open do |db|
|
|
94
94
|
end
|
95
95
|
```
|
96
96
|
|
97
|
+
### using bind variables
|
98
|
+
|
99
|
+
You can use bind variables.
|
100
|
+
|
101
|
+
```ruby
|
102
|
+
con.query('SELECT * FROM users WHERE name = ? AND email = ?', 'Alice', 'alice@example.com')
|
103
|
+
# or
|
104
|
+
con.query('SELECT * FROM users WHERE name = $name AND email = $email', name: 'Alice', email: 'alice@example.com')
|
105
|
+
```
|
106
|
+
|
107
|
+
|
97
108
|
### using BLOB column
|
98
109
|
|
99
110
|
BLOB is available with DuckDB v0.2.5 or later.
|
data/ext/duckdb/extconf.rb
CHANGED
@@ -9,6 +9,14 @@ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE q
|
|
9
9
|
static VALUE duckdb_prepared_statement_nparams(VALUE self);
|
10
10
|
static VALUE duckdb_prepared_statement_execute(VALUE self);
|
11
11
|
static idx_t check_index(VALUE vidx);
|
12
|
+
|
13
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
14
|
+
static VALUE duckdb_prepared_statement_bind_parameter_index(VALUE self, VALUE name);
|
15
|
+
#ifdef HAVE_DUCKDB_PARAMETER_NAME
|
16
|
+
static VALUE duckdb_prepared_statement_parameter_name(VALUE self, VALUE vidx);
|
17
|
+
#endif
|
18
|
+
#endif
|
19
|
+
|
12
20
|
static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val);
|
13
21
|
static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val);
|
14
22
|
static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val);
|
@@ -93,6 +101,39 @@ static idx_t check_index(VALUE vidx) {
|
|
93
101
|
return idx;
|
94
102
|
}
|
95
103
|
|
104
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
105
|
+
static VALUE duckdb_prepared_statement_bind_parameter_index(VALUE self, VALUE name) {
|
106
|
+
rubyDuckDBPreparedStatement *ctx;
|
107
|
+
idx_t idx;
|
108
|
+
|
109
|
+
TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
|
110
|
+
|
111
|
+
if (duckdb_bind_parameter_index(ctx->prepared_statement, &idx, StringValuePtr(name)) == DuckDBError) {;
|
112
|
+
rb_raise(rb_eArgError, "parameter '%s' not found", StringValuePtr(name));
|
113
|
+
}
|
114
|
+
return ULL2NUM(idx);
|
115
|
+
}
|
116
|
+
|
117
|
+
#ifdef HAVE_DUCKDB_PARAMETER_NAME
|
118
|
+
static VALUE duckdb_prepared_statement_parameter_name(VALUE self, VALUE vidx) {
|
119
|
+
rubyDuckDBPreparedStatement *ctx;
|
120
|
+
VALUE vname;
|
121
|
+
const char *name;
|
122
|
+
idx_t idx = check_index(vidx);
|
123
|
+
|
124
|
+
TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
|
125
|
+
|
126
|
+
name = duckdb_parameter_name(ctx->prepared_statement, idx);
|
127
|
+
if (name == NULL) {
|
128
|
+
rb_raise(eDuckDBError, "fail to get name of %llu parameter", (unsigned long long)idx);
|
129
|
+
}
|
130
|
+
vname = rb_str_new2(name);
|
131
|
+
duckdb_free((void *)name);
|
132
|
+
return vname;
|
133
|
+
}
|
134
|
+
#endif /* HAVE_DUCKDB_PARAMETER_NAME */
|
135
|
+
#endif /* HAVE_DUCKDB_H_GE_V090 */
|
136
|
+
|
96
137
|
static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val) {
|
97
138
|
rubyDuckDBPreparedStatement *ctx;
|
98
139
|
idx_t idx = check_index(vidx);
|
@@ -308,6 +349,14 @@ void init_duckdb_prepared_statement(void) {
|
|
308
349
|
rb_define_method(cDuckDBPreparedStatement, "initialize", duckdb_prepared_statement_initialize, 2);
|
309
350
|
rb_define_method(cDuckDBPreparedStatement, "execute", duckdb_prepared_statement_execute, 0);
|
310
351
|
rb_define_method(cDuckDBPreparedStatement, "nparams", duckdb_prepared_statement_nparams, 0);
|
352
|
+
|
353
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
354
|
+
rb_define_method(cDuckDBPreparedStatement, "bind_parameter_index", duckdb_prepared_statement_bind_parameter_index, 1);
|
355
|
+
#ifdef HAVE_DUCKDB_PARAMETER_NAME
|
356
|
+
rb_define_method(cDuckDBPreparedStatement, "parameter_name", duckdb_prepared_statement_parameter_name, 1);
|
357
|
+
#endif
|
358
|
+
#endif
|
359
|
+
|
311
360
|
rb_define_method(cDuckDBPreparedStatement, "bind_bool", duckdb_prepared_statement_bind_bool, 2);
|
312
361
|
rb_define_method(cDuckDBPreparedStatement, "bind_int8", duckdb_prepared_statement_bind_int8, 2);
|
313
362
|
rb_define_method(cDuckDBPreparedStatement, "bind_int16", duckdb_prepared_statement_bind_int16, 2);
|
data/lib/duckdb/connection.rb
CHANGED
@@ -12,7 +12,6 @@ module DuckDB
|
|
12
12
|
# executes sql with args.
|
13
13
|
# The first argument sql must be SQL string.
|
14
14
|
# The rest arguments are parameters of SQL string.
|
15
|
-
# The parameters must be '?' in SQL statement.
|
16
15
|
#
|
17
16
|
# require 'duckdb'
|
18
17
|
# db = DuckDB::Database.open('duckdb_file')
|
@@ -21,12 +20,20 @@ module DuckDB
|
|
21
20
|
# sql = 'SELECT * FROM users WHERE name = ? AND email = ?'
|
22
21
|
# dave = con.query(sql, 'Dave', 'dave@example.com')
|
23
22
|
#
|
24
|
-
|
25
|
-
|
23
|
+
# # or You can use named parameter.
|
24
|
+
#
|
25
|
+
# sql = 'SELECT * FROM users WHERE name = $name AND email = $email'
|
26
|
+
# dave = con.query(sql, name: 'Dave', email: 'dave@example.com')
|
27
|
+
#
|
28
|
+
def query(sql, *args, **hash)
|
29
|
+
return query_sql(sql) if args.empty? && hash.empty?
|
26
30
|
|
27
31
|
stmt = PreparedStatement.new(self, sql)
|
28
|
-
args.
|
29
|
-
stmt.bind(i
|
32
|
+
args.each.with_index(1) do |arg, i|
|
33
|
+
stmt.bind(i, arg)
|
34
|
+
end
|
35
|
+
hash.each do |key, value|
|
36
|
+
stmt.bind(key, value)
|
30
37
|
end
|
31
38
|
stmt.execute
|
32
39
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'date'
|
2
2
|
require 'bigdecimal'
|
3
|
-
require_relative '
|
3
|
+
require_relative 'converter'
|
4
4
|
|
5
5
|
module DuckDB
|
6
6
|
# The DuckDB::PreparedStatement encapsulates connection with DuckDB prepared
|
@@ -167,35 +167,55 @@ module DuckDB
|
|
167
167
|
# sql ='SELECT name, email FROM users WHERE email = ?'
|
168
168
|
# stmt = PreparedStatement.new(con, sql)
|
169
169
|
# stmt.bind(1, 'email@example.com')
|
170
|
-
def bind(
|
170
|
+
def bind(index, value)
|
171
|
+
case index
|
172
|
+
when Integer
|
173
|
+
bind_with_index(index, value)
|
174
|
+
when String
|
175
|
+
bind_with_name(index, value)
|
176
|
+
when Symbol
|
177
|
+
bind_with_name(index.to_s, value)
|
178
|
+
else
|
179
|
+
raise(ArgumentError, "1st argument `#{index}` must be Integer or String or Symbol.")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
private
|
184
|
+
|
185
|
+
def bind_with_index(index, value)
|
171
186
|
case value
|
172
187
|
when NilClass
|
173
|
-
bind_null(
|
188
|
+
bind_null(index)
|
174
189
|
when Float
|
175
|
-
bind_double(
|
190
|
+
bind_double(index, value)
|
176
191
|
when Integer
|
177
192
|
case value
|
178
193
|
when RANGE_INT64
|
179
|
-
bind_int64(
|
194
|
+
bind_int64(index, value)
|
180
195
|
else
|
181
|
-
bind_varchar(
|
196
|
+
bind_varchar(index, value.to_s)
|
182
197
|
end
|
183
198
|
when String
|
184
|
-
blob?(value) ? bind_blob(
|
199
|
+
blob?(value) ? bind_blob(index, value) : bind_varchar(index, value)
|
185
200
|
when TrueClass, FalseClass
|
186
|
-
bind_bool(
|
201
|
+
bind_bool(index, value)
|
187
202
|
when Time
|
188
|
-
bind_varchar(
|
203
|
+
bind_varchar(index, value.strftime('%Y-%m-%d %H:%M:%S.%N'))
|
189
204
|
when Date
|
190
|
-
bind_varchar(
|
205
|
+
bind_varchar(index, value.strftime('%Y-%m-%d'))
|
191
206
|
when BigDecimal
|
192
|
-
bind_varchar(
|
207
|
+
bind_varchar(index, value.to_s('F'))
|
193
208
|
else
|
194
209
|
raise(DuckDB::Error, "not supported type `#{value}` (#{value.class})")
|
195
210
|
end
|
196
211
|
end
|
197
212
|
|
198
|
-
|
213
|
+
def bind_with_name(name, value)
|
214
|
+
raise DuckDB::Error, 'not supported binding with name' unless respond_to?(:bind_parameter_index)
|
215
|
+
|
216
|
+
i = bind_parameter_index(name)
|
217
|
+
bind_with_index(i, value)
|
218
|
+
end
|
199
219
|
|
200
220
|
def blob?(value)
|
201
221
|
value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
|
data/lib/duckdb/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duckdb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Masaki Suketa
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|