duckdb 1.1.1.0 → 1.1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 84935b6317fa4bef4b62197645f061b179e3358e93cba3b976672eb1988715fc
4
- data.tar.gz: 7ff6b2f4b46ea16bcfa2e7de486e9a5bb30aa7d4dccb14e32af7b9886d6fcac4
3
+ metadata.gz: f326104e9d96a1fce6a508d481101c37eca2b12a421eb2ddb07acb838f14c118
4
+ data.tar.gz: 999db21104bb772564ecb41bbc2fee06d728f65618bb8538d14bc20c22173424
5
5
  SHA512:
6
- metadata.gz: d90dbdbf57d5cc282049f6297d00674ff57d9fafbfd7bfab8db8c87fb1153d3c9ea93ceda3b440d066c24ceef5dd1e349dedea6f4b17557bda590bb92f93fc5a
7
- data.tar.gz: cbcbd5c50c6ddc92c01001b36cbe5aad8a87729ea5518a881dcf8c21621679d1c3740c0ed97672d597aca351ea09548d6f7b5e722fde32077cb811a57c3dfd40
6
+ metadata.gz: 6cb7f30f39a2b768d1d6441e324f2c86f910f7af2cff9ca403b91eeb13cacbc0bee56dc54d3786f58e27af9276ae91d4a2ce22c705727b0c8ef5cd3251ab83fe
7
+ data.tar.gz: f17ea13a5aca9640e17e8983a37f9ba88e6ace381d5ad7e979232b0158028b92aa07ddea758ffdd9868511fb2b868354f7f15c20d6c14fb4f2e537613f8ee670
@@ -15,8 +15,8 @@ jobs:
15
15
  runs-on: macos-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.1.6', '3.2.5', '3.3.5', '3.4.0-preview1', 'head']
19
- duckdb: ['1.1.1', '1.1.0', '1.0.0']
18
+ ruby: ['3.1.6', '3.2.5', '3.3.5', '3.4.0-preview2', 'head']
19
+ duckdb: ['1.1.2', '1.1.1', '1.0.0']
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v4
@@ -15,8 +15,8 @@ jobs:
15
15
  runs-on: ubuntu-latest
16
16
  strategy:
17
17
  matrix:
18
- ruby: ['3.1.6', '3.2.5', '3.3.5', '3.4.0-preview1', 'head']
19
- duckdb: ['1.1.1', '1.1.0', '1.0.0']
18
+ ruby: ['3.1.6', '3.2.5', '3.3.5', '3.4.0-preview2', 'head']
19
+ duckdb: ['1.1.2', '1.1.1', '1.0.0']
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v4
@@ -16,7 +16,7 @@ jobs:
16
16
  strategy:
17
17
  matrix:
18
18
  ruby: ['3.1.6', '3.2.5', '3.3.5', 'ucrt', 'mingw', 'mswin', 'head']
19
- duckdb: ['1.1.1', '1.1.0', '1.0.0']
19
+ duckdb: ['1.1.2', '1.1.1', '1.0.0']
20
20
 
21
21
  steps:
22
22
  - uses: actions/checkout@v4
data/.gitignore CHANGED
@@ -15,3 +15,4 @@
15
15
  *.obj
16
16
  *.so
17
17
  Makefile
18
+ ng_test
data/CHANGELOG.md CHANGED
@@ -3,8 +3,29 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  # Unreleased
5
5
 
6
+ # 1.1.2.1 - 2024-11-04
7
+ - `DuckDB::Connection#query` accepts multiple SQL statement.
8
+ - When multiple SQL statements are given, `DuckDB::Connection#query` returns the last statement result.
9
+ - `DuckDB::Connection#query` does not support multiple SQL statements with bind parameters. If you pass 2 or more argument,
10
+ `DuckDB::Connection#query` will regard first argument as only one SQL statement and the rest as bind parameters.
11
+ - add `DuckDB::ExtracteStatements#each` method.
12
+ - add `DuckDB::ExtracteStatementsImpl#destroy` method.
13
+ - add `DuckDB::PreparedStatement#prepare`.
14
+ - `DuckDB::Connection#prepared_statement` accepts block and calls `PreparedStatement#destroy` after block executed.
15
+ ```ruby
16
+ con.prepared_statement('SELECT * FROM table WHERE id = ?') do |stmt|
17
+ stmt.bind(1)
18
+ stmt.execute
19
+ end
20
+ ```
21
+ # 1.1.2.0 - 2024-10-20
22
+ - bump duckdb to 1.1.2.
23
+ - add `DuckDB::PreparedStatement#destroy`.
24
+ - `DuckDB::Connection#query`, `DuckDB::Connection#async_query`, `DuckDB::Connection#async_query_stream` call
25
+ `DuckDB::PreparedStatement#destroy` to free the prepared statement immediately (#775, #781).
26
+
6
27
  # 1.1.1.0 - 2024-10-06
7
- - bump duckdb 1.1.1.
28
+ - bump duckdb to 1.1.1.
8
29
  ## Breaking changes
9
30
  - drop duckdb v0.10.x.
10
31
 
data/CONTRIBUTION.md CHANGED
@@ -14,7 +14,7 @@ docker compose run --rm ubuntu bash
14
14
 
15
15
  In case you want custom ruby or duckdb versions, use `--build-arg` options
16
16
  ```
17
- docker-compose build ubuntu --build-arg RUBY_VERSION=3.1.3 --build-arg DUCKDB_VERSION=0.6.0
17
+ docker compose build ubuntu --build-arg RUBY_VERSION=3.1.3 --build-arg DUCKDB_VERSION=1.0.0
18
18
  ```
19
19
 
20
20
  ### Without docker
data/Dockerfile CHANGED
@@ -1,7 +1,7 @@
1
1
  ARG RUBY_VERSION=3.3.5
2
2
  FROM ruby:${RUBY_VERSION}
3
3
 
4
- ARG DUCKDB_VERSION=1.1.1
4
+ ARG DUCKDB_VERSION=1.1.2
5
5
 
6
6
  RUN apt update -qq && \
7
7
  apt install -y build-essential curl git wget
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in duckdb.gemspec
4
4
  gemspec
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- duckdb (1.1.1.0)
4
+ duckdb (1.1.2.1)
5
5
  bigdecimal (>= 3.1.4)
6
6
 
7
7
  GEM
@@ -17,6 +17,7 @@ static VALUE allocate(VALUE klass);
17
17
  static size_t memsize(const void *p);
18
18
 
19
19
  static VALUE duckdb_extracted_statements_initialize(VALUE self, VALUE con, VALUE query);
20
+ static VALUE duckdb_extracted_statements_destroy(VALUE self);
20
21
  static VALUE duckdb_extracted_statements_size(VALUE self);
21
22
  static VALUE duckdb_extracted_statements_prepared_statement(VALUE self, VALUE con, VALUE index);
22
23
 
@@ -56,12 +57,22 @@ static VALUE duckdb_extracted_statements_initialize(VALUE self, VALUE con, VALUE
56
57
 
57
58
  if (ctx->num_statements == 0) {
58
59
  error = duckdb_extract_statements_error(ctx->extracted_statements);
59
- rb_raise(eDuckDBError, "%s", error);
60
+ rb_raise(eDuckDBError, "%s", error ? error : "Failed to extract statements(Database connection closed?).");
60
61
  }
61
62
 
62
63
  return self;
63
64
  }
64
65
 
66
+ static VALUE duckdb_extracted_statements_destroy(VALUE self) {
67
+ rubyDuckDBExtractedStatements *ctx;
68
+
69
+ TypedData_Get_Struct(self, rubyDuckDBExtractedStatements, &extract_statements_data_type, ctx);
70
+
71
+ duckdb_destroy_extracted(&(ctx->extracted_statements));
72
+
73
+ return Qnil;
74
+ }
75
+
65
76
  static VALUE duckdb_extracted_statements_size(VALUE self) {
66
77
  rubyDuckDBExtractedStatements *ctx;
67
78
 
@@ -85,10 +96,11 @@ static VALUE duckdb_extracted_statements_prepared_statement(VALUE self, VALUE co
85
96
  }
86
97
 
87
98
  void rbduckdb_init_duckdb_extracted_statements(void) {
88
- cDuckDBExtractedStatements = rb_define_class_under(mDuckDB, "ExtractedStatements", rb_cObject);
99
+ cDuckDBExtractedStatements = rb_define_class_under(mDuckDB, "ExtractedStatementsImpl", rb_cObject);
89
100
 
90
101
  rb_define_alloc_func(cDuckDBExtractedStatements, allocate);
91
102
  rb_define_method(cDuckDBExtractedStatements, "initialize", duckdb_extracted_statements_initialize, 2);
103
+ rb_define_method(cDuckDBExtractedStatements, "destroy", duckdb_extracted_statements_destroy, 0);
92
104
  rb_define_method(cDuckDBExtractedStatements, "size", duckdb_extracted_statements_size, 0);
93
105
  rb_define_method(cDuckDBExtractedStatements, "prepared_statement", duckdb_extracted_statements_prepared_statement, 2);
94
106
  }
@@ -2,12 +2,14 @@
2
2
 
3
3
  VALUE cDuckDBPreparedStatement;
4
4
 
5
+ static void destroy_prepared_statement(rubyDuckDBPreparedStatement *p);
5
6
  static void deallocate(void *ctx);
6
7
  static VALUE allocate(VALUE klass);
7
8
  static size_t memsize(const void *p);
8
9
  static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query);
9
10
  static VALUE duckdb_prepared_statement_nparams(VALUE self);
10
11
  static VALUE duckdb_prepared_statement_execute(VALUE self);
12
+ static VALUE duckdb_prepared_statement_destroy(VALUE self);
11
13
  static idx_t check_index(VALUE vidx);
12
14
 
13
15
  static VALUE duckdb_prepared_statement_bind_parameter_index(VALUE self, VALUE name);
@@ -30,6 +32,7 @@ static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE
30
32
  static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
31
33
  static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros);
32
34
  static VALUE duckdb_prepared_statement__bind_hugeint(VALUE self, VALUE vidx, VALUE lower, VALUE upper);
35
+ static VALUE duckdb_prepared_statement__bind_decimal(VALUE self, VALUE vidx, VALUE lower, VALUE upper, VALUE width, VALUE scale);
33
36
 
34
37
  static const rb_data_type_t prepared_statement_data_type = {
35
38
  "DuckDB/PreparedStatement",
@@ -37,10 +40,17 @@ static const rb_data_type_t prepared_statement_data_type = {
37
40
  0, 0, RUBY_TYPED_FREE_IMMEDIATELY
38
41
  };
39
42
 
43
+ static void destroy_prepared_statement(rubyDuckDBPreparedStatement *p) {
44
+ if (p->prepared_statement) {
45
+ duckdb_destroy_prepare(&(p->prepared_statement));
46
+ }
47
+ }
48
+
40
49
  static void deallocate(void *ctx) {
41
50
  rubyDuckDBPreparedStatement *p = (rubyDuckDBPreparedStatement *)ctx;
42
51
 
43
- duckdb_destroy_prepare(&(p->prepared_statement));
52
+ destroy_prepared_statement(p);
53
+ // duckdb_destroy_prepare(&(p->prepared_statement));
44
54
  xfree(p);
45
55
  }
46
56
 
@@ -62,7 +72,7 @@ VALUE rbduckdb_prepared_statement_new(duckdb_connection con, duckdb_extracted_st
62
72
  TypedData_Get_Struct(obj, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
63
73
 
64
74
  if (duckdb_prepare_extracted_statement(con, extracted_statements, index, &(ctx->prepared_statement)) == DuckDBError) {
65
- rb_raise(eDuckDBError, "Fail to get DuckDB::PreparedStatement object from ExtractedStatements object");
75
+ rb_raise(eDuckDBError, "Failed to create DuckDB::PreparedStatement object.");
66
76
  }
67
77
  return obj;
68
78
  }
@@ -91,20 +101,37 @@ static VALUE duckdb_prepared_statement_nparams(VALUE self) {
91
101
  return ULL2NUM(duckdb_nparams(ctx->prepared_statement));
92
102
  }
93
103
 
94
-
95
104
  static VALUE duckdb_prepared_statement_execute(VALUE self) {
96
105
  rubyDuckDBPreparedStatement *ctx;
97
106
  rubyDuckDBResult *ctxr;
98
107
  VALUE result = rbduckdb_create_result();
108
+ const char *p = NULL;
99
109
 
100
110
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
101
111
  ctxr = get_struct_result(result);
102
112
  if (duckdb_execute_prepared(ctx->prepared_statement, &(ctxr->result)) == DuckDBError) {
103
- rb_raise(eDuckDBError, "%s", duckdb_result_error(&(ctxr->result)));
113
+ p = duckdb_result_error(&(ctxr->result));
114
+ if (p == NULL) {
115
+ p = duckdb_prepare_error(ctx->prepared_statement);
116
+ }
117
+ rb_raise(eDuckDBError, "%s", p ? p : "Failed to execute prepared statement.");
104
118
  }
105
119
  return result;
106
120
  }
107
121
 
122
+ /*
123
+ * :nodoc:
124
+ */
125
+ static VALUE duckdb_prepared_statement_destroy(VALUE self) {
126
+ rubyDuckDBPreparedStatement *ctx;
127
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
128
+ destroy_prepared_statement(ctx);
129
+ /*
130
+ ctx->prepared_statement = NULL;
131
+ */
132
+ return Qnil;
133
+ }
134
+
108
135
  static idx_t check_index(VALUE vidx) {
109
136
  idx_t idx = NUM2ULL(vidx);
110
137
  if (idx <= 0) {
@@ -378,6 +405,26 @@ static VALUE duckdb_prepared_statement__bind_hugeint(VALUE self, VALUE vidx, VAL
378
405
  return self;
379
406
  }
380
407
 
408
+ static VALUE duckdb_prepared_statement__bind_decimal(VALUE self, VALUE vidx, VALUE lower, VALUE upper, VALUE width, VALUE scale) {
409
+ duckdb_hugeint hugeint;
410
+ duckdb_decimal decimal;
411
+ rubyDuckDBPreparedStatement *ctx;
412
+ idx_t idx = check_index(vidx);
413
+
414
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
415
+ hugeint.lower = NUM2ULL(lower);
416
+ hugeint.upper = NUM2LL(upper);
417
+ decimal.value = hugeint;
418
+ decimal.width = (uint8_t)NUM2UINT(width);
419
+ decimal.scale = (uint8_t)NUM2UINT(scale);
420
+
421
+ if (duckdb_bind_decimal(ctx->prepared_statement, idx, decimal) == DuckDBError) {
422
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
423
+ }
424
+
425
+ return self;
426
+ }
427
+
381
428
  rubyDuckDBPreparedStatement *get_struct_prepared_statement(VALUE self) {
382
429
  rubyDuckDBPreparedStatement *ctx;
383
430
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
@@ -391,6 +438,7 @@ void rbduckdb_init_duckdb_prepared_statement(void) {
391
438
 
392
439
  rb_define_method(cDuckDBPreparedStatement, "initialize", duckdb_prepared_statement_initialize, 2);
393
440
  rb_define_method(cDuckDBPreparedStatement, "execute", duckdb_prepared_statement_execute, 0);
441
+ rb_define_method(cDuckDBPreparedStatement, "destroy", duckdb_prepared_statement_destroy, 0);
394
442
  rb_define_method(cDuckDBPreparedStatement, "nparams", duckdb_prepared_statement_nparams, 0);
395
443
  rb_define_method(cDuckDBPreparedStatement, "bind_parameter_index", duckdb_prepared_statement_bind_parameter_index, 1);
396
444
  rb_define_method(cDuckDBPreparedStatement, "parameter_name", duckdb_prepared_statement_parameter_name, 1);
@@ -412,4 +460,5 @@ void rbduckdb_init_duckdb_prepared_statement(void) {
412
460
  rb_define_private_method(cDuckDBPreparedStatement, "_bind_timestamp", duckdb_prepared_statement__bind_timestamp, 8);
413
461
  rb_define_private_method(cDuckDBPreparedStatement, "_bind_interval", duckdb_prepared_statement__bind_interval, 4);
414
462
  rb_define_private_method(cDuckDBPreparedStatement, "_bind_hugeint", duckdb_prepared_statement__bind_hugeint, 3);
463
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_decimal", duckdb_prepared_statement__bind_decimal, 5);
415
464
  }
@@ -74,16 +74,7 @@ module DuckDB
74
74
  # appender.flush
75
75
  #
76
76
  def append_date(value)
77
- date = case value
78
- when Date, Time
79
- value
80
- else
81
- begin
82
- Date.parse(value)
83
- rescue
84
- raise(ArgumentError, "Cannot parse argument `#{value}` to Date.")
85
- end
86
- end
77
+ date = to_date(value)
87
78
 
88
79
  _append_date(date.year, date.month, date.day)
89
80
  end
@@ -126,18 +117,7 @@ module DuckDB
126
117
  # appender.flush
127
118
  #
128
119
  def append_timestamp(value)
129
- time = case value
130
- when Time
131
- value
132
- when Date
133
- value.to_time
134
- else
135
- begin
136
- Time.parse(value)
137
- rescue
138
- raise(ArgumentError, "Cannot parse argument `#{value}` to Time or Date.")
139
- end
140
- end
120
+ time = to_time(value)
141
121
 
142
122
  _append_timestamp(time.year, time.month, time.day, time.hour, time.min, time.sec, time.nsec / 1000)
143
123
  end
@@ -233,5 +213,33 @@ module DuckDB
233
213
  def blob?(value)
234
214
  value.instance_of?(DuckDB::Blob) || value.encoding == Encoding::BINARY
235
215
  end
216
+
217
+ def to_date(value)
218
+ case value
219
+ when Date, Time
220
+ value
221
+ else
222
+ begin
223
+ Date.parse(value)
224
+ rescue StandardError
225
+ raise(ArgumentError, "Cannot parse argument `#{value}` to Date.")
226
+ end
227
+ end
228
+ end
229
+
230
+ def to_time(value)
231
+ case value
232
+ when Time
233
+ value
234
+ when Date
235
+ value.to_time
236
+ else
237
+ begin
238
+ Time.parse(value)
239
+ rescue StandardError
240
+ raise(ArgumentError, "Cannot parse argument `#{value}` to Time or Date.")
241
+ end
242
+ end
243
+ end
236
244
  end
237
245
  end
@@ -26,11 +26,23 @@ module DuckDB
26
26
  # dave = con.query(sql, name: 'Dave', email: 'dave@example.com')
27
27
  #
28
28
  def query(sql, *args, **kwargs)
29
- return query_sql(sql) if args.empty? && kwargs.empty?
29
+ return query_multi_sql(sql) if args.empty? && kwargs.empty?
30
30
 
31
- stmt = PreparedStatement.new(self, sql)
32
- stmt.bind_args(*args, **kwargs)
33
- stmt.execute
31
+ prepare(sql) do |stmt|
32
+ stmt.bind_args(*args, **kwargs)
33
+ stmt.execute
34
+ end
35
+ end
36
+
37
+ def query_multi_sql(sql)
38
+ stmts = ExtractedStatements.new(self, sql)
39
+ result = nil
40
+ stmts.each do |stmt|
41
+ result = stmt.execute
42
+ end
43
+ result
44
+ ensure
45
+ stmts&.destroy
34
46
  end
35
47
 
36
48
  #
@@ -50,9 +62,10 @@ module DuckDB
50
62
  # result.each.first
51
63
  #
52
64
  def async_query(sql, *args, **kwargs)
53
- stmt = PreparedStatement.new(self, sql)
54
- stmt.bind_args(*args, **kwargs)
55
- stmt.pending_prepared
65
+ prepare(sql) do |stmt|
66
+ stmt.bind_args(*args, **kwargs)
67
+ stmt.pending_prepared
68
+ end
56
69
  end
57
70
 
58
71
  #
@@ -73,9 +86,10 @@ module DuckDB
73
86
  # result.each.first
74
87
  #
75
88
  def async_query_stream(sql, *args, **kwargs)
76
- stmt = PreparedStatement.new(self, sql)
77
- stmt.bind_args(*args, **kwargs)
78
- stmt.pending_prepared_stream
89
+ prepare(sql) do |stmt|
90
+ stmt.bind_args(*args, **kwargs)
91
+ stmt.pending_prepared_stream
92
+ end
79
93
  end
80
94
 
81
95
  #
@@ -96,6 +110,8 @@ module DuckDB
96
110
  #
97
111
  # returns PreparedStatement object.
98
112
  # The first argument is SQL string.
113
+ # If block is given, the block is executed with PreparedStatement object
114
+ # and the object is cleaned up immediately.
99
115
  #
100
116
  # require 'duckdb'
101
117
  # db = DuckDB::Database.open('duckdb_file')
@@ -105,8 +121,17 @@ module DuckDB
105
121
  # stmt = con.prepared_statement(sql)
106
122
  # stmt.bind_args(name: 'Dave', email: 'dave@example.com')
107
123
  # result = stmt.execute
108
- def prepared_statement(str)
109
- PreparedStatement.new(self, str)
124
+ #
125
+ # # or
126
+ # result = con.prepared_statement(sql) do |stmt|
127
+ # stmt.bind_args(name: 'Dave', email: 'dave@example.com')
128
+ # stmt.execute
129
+ # end
130
+ #
131
+ def prepared_statement(str, &)
132
+ return PreparedStatement.new(self, str) unless block_given?
133
+
134
+ PreparedStatement.prepare(self, str, &)
110
135
  end
111
136
 
112
137
  #
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DuckDB
4
+ class ExtractedStatements < ExtractedStatementsImpl
5
+ include Enumerable
6
+
7
+ def initialize(con, sql)
8
+ @con = con
9
+ super(con, sql)
10
+ end
11
+
12
+ def each
13
+ return to_enum(__method__) { size } unless block_given?
14
+
15
+ size.times do |i|
16
+ yield prepared_statement(@con, i)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -22,6 +22,31 @@ module DuckDB
22
22
  RANGE_INT32 = -2_147_483_648..2_147_483_647
23
23
  RANGE_INT64 = -9_223_372_036_854_775_808..9_223_372_036_854_775_807
24
24
 
25
+ class << self
26
+ # return DuckDB::PreparedStatement object.
27
+ # The first argument is DuckDB::Connection object.
28
+ # The second argument is SQL string.
29
+ # If block is given, the block is executed and the statement is destroyed.
30
+ #
31
+ # require 'duckdb'
32
+ # db = DuckDB::Database.open('duckdb_database')
33
+ # con = db.connection
34
+ # DuckDB::PreparedStatement.prepare(con, 'SELECT * FROM users WHERE id = ?') do |stmt|
35
+ # stmt.bind(1, 1)
36
+ # stmt.execute
37
+ # end
38
+ def prepare(con, sql)
39
+ stmt = new(con, sql)
40
+ return stmt unless block_given?
41
+
42
+ begin
43
+ yield stmt
44
+ ensure
45
+ stmt.destroy
46
+ end
47
+ end
48
+ end
49
+
25
50
  def pending_prepared
26
51
  PendingResult.new(self)
27
52
  end
@@ -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 = '1.1.1.0'
6
+ VERSION = '1.1.2.1'
7
7
  end
data/lib/duckdb.rb CHANGED
@@ -6,6 +6,7 @@ require 'duckdb/version'
6
6
  require 'duckdb/converter'
7
7
  require 'duckdb/database'
8
8
  require 'duckdb/connection'
9
+ require 'duckdb/extracted_statements'
9
10
  require 'duckdb/result'
10
11
  require 'duckdb/prepared_statement'
11
12
  require 'duckdb/pending_result'
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: 1.1.1.0
4
+ version: 1.1.2.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: 2024-10-06 00:00:00.000000000 Z
11
+ date: 2024-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bigdecimal
@@ -149,6 +149,7 @@ files:
149
149
  - lib/duckdb/converter.rb
150
150
  - lib/duckdb/converter/int_to_sym.rb
151
151
  - lib/duckdb/database.rb
152
+ - lib/duckdb/extracted_statements.rb
152
153
  - lib/duckdb/infinity.rb
153
154
  - lib/duckdb/interval.rb
154
155
  - lib/duckdb/library_version.rb