duckdb 0.9.0 → 0.9.0.1

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: f7738df010c1fb1aab32b61077ff9409566cfaddecfef3b27aa6e7ee7a8651f2
4
- data.tar.gz: 6357f43da56b7c4fbea72ec7b3c549f598f3a91b88c1c91ab5320a01606f3589
3
+ metadata.gz: aac4fbdeca8ed41cef872ace9dd3c8784ce43ee224a733f469fcd0907e852cd5
4
+ data.tar.gz: 56c8a5831830264fd4dfac41ba7a60bb9e6493a40536a5502c10dc0fc41b16d7
5
5
  SHA512:
6
- metadata.gz: e417badc1b301fdea9f3f4b27648e7e1c7d8e125a0a1323bb69e93a992467eca0a57a320b0bb14f7fda45bf8d9d3706b59eb586a71e3c9f77bd2ec18c88b8b3a
7
- data.tar.gz: b1486d0d525fa93a8485504eac95015a07ac064a4dfb15bb0689aa7be4cb41edcf03436324e822bda26a8c3c6e8a9e2a690efcd49f7180f675777f75284df5e8
6
+ metadata.gz: b94ffce97a54769bae379a3b13765b2132df1efe80fdb8f4855f77248855e95e9370651dbbe165a64c6ee45aff5bef20b3800a680f3da5287528974a243af338
7
+ data.tar.gz: 96accf18b7f4df7721efaec8e215e92dcbe97d22a99d89ffb64658f4696eb462b8ceaa27a3e558cba8ef5a7ce257fc4e3b35f83178fadf8047e19280563e7ae6
@@ -15,7 +15,7 @@ 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-preview1', 'head']
18
+ ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-preview2', 'head']
19
19
  duckdb: ['0.9.0', '0.8.1']
20
20
 
21
21
  steps:
@@ -15,7 +15,7 @@ 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-preview1', 'head']
18
+ ruby: ['2.7.8', '3.0.6', '3.1.4', '3.2.2', '3.3.0-preview2', 'head']
19
19
  duckdb: ['0.9.0', '0.8.1']
20
20
 
21
21
  steps:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # ChangeLog
2
2
 
3
+ # 0.9.0.1
4
+
5
+ - add `DuckDB::PreparedStatement#bind_parameter_index`.
6
+ - DuckDB::Connection#query accepts SQL with named bind parameters.
7
+
3
8
  # 0.9.0
4
9
  - bump duckdb to 0.9.0.
5
10
 
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (0.9.0)
4
+ duckdb (0.9.0.1)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
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.
@@ -9,6 +9,11 @@ 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
+ #endif
16
+
12
17
  static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val);
13
18
  static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val);
14
19
  static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val);
@@ -93,6 +98,20 @@ static idx_t check_index(VALUE vidx) {
93
98
  return idx;
94
99
  }
95
100
 
101
+ #ifdef HAVE_DUCKDB_H_GE_V090
102
+ static VALUE duckdb_prepared_statement_bind_parameter_index(VALUE self, VALUE name) {
103
+ rubyDuckDBPreparedStatement *ctx;
104
+ idx_t idx;
105
+
106
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
107
+
108
+ if (duckdb_bind_parameter_index(ctx->prepared_statement, &idx, StringValuePtr(name)) == DuckDBError) {;
109
+ rb_raise(rb_eArgError, "parameter '%s' not found", StringValuePtr(name));
110
+ }
111
+ return ULL2NUM(idx);
112
+ }
113
+ #endif
114
+
96
115
  static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val) {
97
116
  rubyDuckDBPreparedStatement *ctx;
98
117
  idx_t idx = check_index(vidx);
@@ -308,6 +327,11 @@ void init_duckdb_prepared_statement(void) {
308
327
  rb_define_method(cDuckDBPreparedStatement, "initialize", duckdb_prepared_statement_initialize, 2);
309
328
  rb_define_method(cDuckDBPreparedStatement, "execute", duckdb_prepared_statement_execute, 0);
310
329
  rb_define_method(cDuckDBPreparedStatement, "nparams", duckdb_prepared_statement_nparams, 0);
330
+
331
+ #ifdef HAVE_DUCKDB_H_GE_V090
332
+ rb_define_method(cDuckDBPreparedStatement, "bind_parameter_index", duckdb_prepared_statement_bind_parameter_index, 1);
333
+ #endif
334
+
311
335
  rb_define_method(cDuckDBPreparedStatement, "bind_bool", duckdb_prepared_statement_bind_bool, 2);
312
336
  rb_define_method(cDuckDBPreparedStatement, "bind_int8", duckdb_prepared_statement_bind_int8, 2);
313
337
  rb_define_method(cDuckDBPreparedStatement, "bind_int16", duckdb_prepared_statement_bind_int16, 2);
@@ -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
- def query(sql, *args)
25
- return query_sql(sql) if args.empty?
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.each_with_index do |arg, i|
29
- stmt.bind(i + 1, arg)
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 './converter'
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(i, value)
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(i)
188
+ bind_null(index)
174
189
  when Float
175
- bind_double(i, value)
190
+ bind_double(index, value)
176
191
  when Integer
177
192
  case value
178
193
  when RANGE_INT64
179
- bind_int64(i, value)
194
+ bind_int64(index, value)
180
195
  else
181
- bind_varchar(i, value.to_s)
196
+ bind_varchar(index, value.to_s)
182
197
  end
183
198
  when String
184
- blob?(value) ? bind_blob(i, value) : bind_varchar(i, value)
199
+ blob?(value) ? bind_blob(index, value) : bind_varchar(index, value)
185
200
  when TrueClass, FalseClass
186
- bind_bool(i, value)
201
+ bind_bool(index, value)
187
202
  when Time
188
- bind_varchar(i, value.strftime('%Y-%m-%d %H:%M:%S.%N'))
203
+ bind_varchar(index, value.strftime('%Y-%m-%d %H:%M:%S.%N'))
189
204
  when Date
190
- bind_varchar(i, value.strftime('%Y-%m-%d'))
205
+ bind_varchar(index, value.strftime('%Y-%m-%d'))
191
206
  when BigDecimal
192
- bind_varchar(i, value.to_s('F'))
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
- private
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
@@ -3,5 +3,5 @@
3
3
  module DuckDB
4
4
  # The version string of ruby-duckdb.
5
5
  # Currently, ruby-duckdb is NOT semantic versioning.
6
- VERSION = '0.9.0'
6
+ VERSION = '0.9.0.1'
7
7
  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.9.0
4
+ version: 0.9.0.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-09-29 00:00:00.000000000 Z
11
+ date: 2023-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler