duckdb 0.9.1 → 0.9.1.2

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.
@@ -83,7 +83,7 @@ static VALUE duckdb_prepared_statement_nparams(VALUE self) {
83
83
  static VALUE duckdb_prepared_statement_execute(VALUE self) {
84
84
  rubyDuckDBPreparedStatement *ctx;
85
85
  rubyDuckDBResult *ctxr;
86
- VALUE result = create_result();
86
+ VALUE result = rbduckdb_create_result();
87
87
 
88
88
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
89
89
  ctxr = get_struct_result(result);
@@ -268,7 +268,7 @@ static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE
268
268
  duckdb_date dt;
269
269
  idx_t idx = check_index(vidx);
270
270
 
271
- dt = to_duckdb_date_from_value(year, month, day);
271
+ dt = rbduckdb_to_duckdb_date_from_value(year, month, day);
272
272
 
273
273
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
274
274
 
@@ -285,7 +285,7 @@ static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE
285
285
 
286
286
  idx_t idx = check_index(vidx);
287
287
 
288
- time = to_duckdb_time_from_value(hour, min, sec, micros);
288
+ time = rbduckdb_to_duckdb_time_from_value(hour, min, sec, micros);
289
289
 
290
290
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
291
291
 
@@ -301,7 +301,7 @@ static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, V
301
301
  rubyDuckDBPreparedStatement *ctx;
302
302
  idx_t idx = check_index(vidx);
303
303
 
304
- timestamp = to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
304
+ timestamp = rbduckdb_to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
305
305
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
306
306
 
307
307
  if (duckdb_bind_timestamp(ctx->prepared_statement, idx, timestamp) == DuckDBError) {
@@ -317,7 +317,7 @@ static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VA
317
317
 
318
318
  TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
319
319
 
320
- to_duckdb_interval_from_value(&interval, months, days, micros);
320
+ rbduckdb_to_duckdb_interval_from_value(&interval, months, days, micros);
321
321
 
322
322
  if (duckdb_bind_interval(ctx->prepared_statement, idx, interval) == DuckDBError) {
323
323
  rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
@@ -341,7 +341,13 @@ static VALUE duckdb_prepared_statement__bind_hugeint(VALUE self, VALUE vidx, VAL
341
341
  return self;
342
342
  }
343
343
 
344
- void init_duckdb_prepared_statement(void) {
344
+ rubyDuckDBPreparedStatement *get_struct_prepared_statement(VALUE self) {
345
+ rubyDuckDBPreparedStatement *ctx;
346
+ TypedData_Get_Struct(self, rubyDuckDBPreparedStatement, &prepared_statement_data_type, ctx);
347
+ return ctx;
348
+ }
349
+
350
+ void rbduckdb_init_duckdb_prepared_statement(void) {
345
351
  cDuckDBPreparedStatement = rb_define_class_under(mDuckDB, "PreparedStatement", rb_cObject);
346
352
 
347
353
  rb_define_alloc_func(cDuckDBPreparedStatement, allocate);
@@ -356,7 +362,6 @@ void init_duckdb_prepared_statement(void) {
356
362
  rb_define_method(cDuckDBPreparedStatement, "parameter_name", duckdb_prepared_statement_parameter_name, 1);
357
363
  #endif
358
364
  #endif
359
-
360
365
  rb_define_method(cDuckDBPreparedStatement, "bind_bool", duckdb_prepared_statement_bind_bool, 2);
361
366
  rb_define_method(cDuckDBPreparedStatement, "bind_int8", duckdb_prepared_statement_bind_int8, 2);
362
367
  rb_define_method(cDuckDBPreparedStatement, "bind_int16", duckdb_prepared_statement_bind_int16, 2);
@@ -8,6 +8,7 @@ struct _rubyDuckDBPreparedStatement {
8
8
 
9
9
  typedef struct _rubyDuckDBPreparedStatement rubyDuckDBPreparedStatement;
10
10
 
11
- void init_duckdb_prepared_statement(void);
11
+ rubyDuckDBPreparedStatement *get_struct_prepared_statement(VALUE self);
12
+ void rbduckdb_init_duckdb_prepared_statement(void);
12
13
 
13
14
  #endif
data/ext/duckdb/result.c CHANGED
@@ -37,7 +37,6 @@ static VALUE duckdb_result__enum_internal_type(VALUE oDuckDBResult, VALUE col_id
37
37
  static VALUE duckdb_result__enum_dictionary_size(VALUE oDuckDBResult, VALUE col_idx);
38
38
  static VALUE duckdb_result__enum_dictionary_value(VALUE oDuckDBResult, VALUE col_idx, VALUE idx);
39
39
 
40
- #ifdef HAVE_DUCKDB_H_GE_V080
41
40
  static VALUE vector_date(void *vector_data, idx_t row_idx);
42
41
  static VALUE vector_timestamp(void* vector_data, idx_t row_idx);
43
42
  static VALUE vector_interval(void* vector_data, idx_t row_idx);
@@ -52,7 +51,6 @@ static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t r
52
51
  static VALUE vector_uuid(void* vector_data, idx_t row_idx);
53
52
  static VALUE vector_value(duckdb_vector vector, idx_t row_idx);
54
53
  static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult);
55
- #endif
56
54
 
57
55
  static const rb_data_type_t result_data_type = {
58
56
  "DuckDB/Result",
@@ -231,7 +229,7 @@ static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
231
229
 
232
230
  VALUE ary = rb_ary_new2(column_count);
233
231
  for(col_idx = 0; col_idx < column_count; col_idx++) {
234
- VALUE column = create_column(oDuckDBResult, col_idx);
232
+ VALUE column = rbduckdb_create_column(oDuckDBResult, col_idx);
235
233
  rb_ary_store(ary, col_idx, column);
236
234
  }
237
235
  return ary;
@@ -399,11 +397,10 @@ static VALUE duckdb_result__enum_dictionary_value(VALUE oDuckDBResult, VALUE col
399
397
  return value;
400
398
  }
401
399
 
402
- VALUE create_result(void) {
400
+ VALUE rbduckdb_create_result(void) {
403
401
  return allocate(cDuckDBResult);
404
402
  }
405
403
 
406
- #ifdef HAVE_DUCKDB_H_GE_V080
407
404
  static VALUE vector_date(void *vector_data, idx_t row_idx) {
408
405
  duckdb_date_struct date = duckdb_from_date(((duckdb_date *) vector_data)[row_idx]);
409
406
 
@@ -719,9 +716,8 @@ static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult) {
719
716
  }
720
717
  return Qnil;
721
718
  }
722
- #endif
723
719
 
724
- void init_duckdb_result(void) {
720
+ void rbduckdb_init_duckdb_result(void) {
725
721
  cDuckDBResult = rb_define_class_under(mDuckDB, "Result", rb_cObject);
726
722
  rb_define_alloc_func(cDuckDBResult, allocate);
727
723
 
@@ -746,7 +742,5 @@ void init_duckdb_result(void) {
746
742
  rb_define_private_method(cDuckDBResult, "_enum_internal_type", duckdb_result__enum_internal_type, 1);
747
743
  rb_define_private_method(cDuckDBResult, "_enum_dictionary_size", duckdb_result__enum_dictionary_size, 1);
748
744
  rb_define_private_method(cDuckDBResult, "_enum_dictionary_value", duckdb_result__enum_dictionary_value, 2);
749
- #ifdef HAVE_DUCKDB_H_GE_V080
750
745
  rb_define_method(cDuckDBResult, "chunk_each", duckdb_result_chunk_each, 0);
751
- #endif
752
746
  }
data/ext/duckdb/result.h CHANGED
@@ -8,8 +8,8 @@ struct _rubyDuckDBResult {
8
8
  typedef struct _rubyDuckDBResult rubyDuckDBResult;
9
9
 
10
10
  rubyDuckDBResult *get_struct_result(VALUE obj);
11
- void init_duckdb_result(void);
12
- VALUE create_result(void);
11
+ void rbduckdb_init_duckdb_result(void);
12
+ VALUE rbduckdb_create_result(void);
13
13
 
14
14
  #endif
15
15
 
@@ -4,14 +4,6 @@
4
4
  #include "ruby.h"
5
5
  #include <duckdb.h>
6
6
 
7
- #ifdef HAVE_DUCKDB_EXTRACT_STATEMENTS
8
- #define HAVE_DUCKDB_H_GE_V070 1
9
- #endif
10
-
11
- #ifdef HAVE_DUCKDB_STRING_IS_INLINED
12
- #define HAVE_DUCKDB_H_GE_V080 1
13
- #endif
14
-
15
7
  #ifdef HAVE_DUCKDB_BIND_PARAMETER_INDEX
16
8
  #define HAVE_DUCKDB_H_GE_V090 1
17
9
  #endif
@@ -22,6 +14,7 @@
22
14
  #include "./result.h"
23
15
  #include "./column.h"
24
16
  #include "./prepared_statement.h"
17
+ #include "./pending_result.h"
25
18
  #include "./util.h"
26
19
  #include "./converter.h"
27
20
 
data/ext/duckdb/util.c CHANGED
@@ -1,6 +1,6 @@
1
1
  #include "ruby-duckdb.h"
2
2
 
3
- duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day) {
3
+ duckdb_date rbduckdb_to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day) {
4
4
  duckdb_date_struct dt_struct;
5
5
 
6
6
  dt_struct.year = NUM2INT(year);
@@ -10,7 +10,7 @@ duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day) {
10
10
  return duckdb_to_date(dt_struct);
11
11
  }
12
12
 
13
- duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros) {
13
+ duckdb_time rbduckdb_to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros) {
14
14
  duckdb_time_struct time_st;
15
15
 
16
16
  time_st.hour = NUM2INT(hour);
@@ -21,7 +21,7 @@ duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE mi
21
21
  return duckdb_to_time(time_st);
22
22
  }
23
23
 
24
- duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
24
+ duckdb_timestamp rbduckdb_to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
25
25
  duckdb_timestamp_struct timestamp_st;
26
26
 
27
27
  timestamp_st.date.year = NUM2INT(year);
@@ -35,7 +35,7 @@ duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE d
35
35
  return duckdb_to_timestamp(timestamp_st);
36
36
  }
37
37
 
38
- void to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros) {
38
+ void rbduckdb_to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros) {
39
39
  interval->months = NUM2INT(months);
40
40
  interval->days = NUM2INT(days);
41
41
  interval->micros = NUM2LL(micros);
data/ext/duckdb/util.h CHANGED
@@ -1,9 +1,9 @@
1
1
  #ifndef RUBY_DUCKDB_UTIL_H
2
2
  #define RUBY_DUCKDB_UTIL_H
3
3
 
4
- duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day);
5
- duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros);
6
- duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
7
- void to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros);
4
+ duckdb_date rbduckdb_to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day);
5
+ duckdb_time rbduckdb_to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros);
6
+ duckdb_timestamp rbduckdb_to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
7
+ void rbduckdb_to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros);
8
8
 
9
9
  #endif
@@ -86,16 +86,7 @@ module DuckDB
86
86
  # appender.flush
87
87
  #
88
88
  def append_time(value)
89
- time = case value
90
- when Time
91
- value
92
- else
93
- begin
94
- Time.parse(value)
95
- rescue
96
- raise(ArgumentError, "Cannot parse argument `#{value}` to Time.")
97
- end
98
- end
89
+ time = _parse_time(value)
99
90
 
100
91
  _append_time(time.hour, time.min, time.sec, time.usec)
101
92
  end
@@ -25,19 +25,38 @@ module DuckDB
25
25
  # sql = 'SELECT * FROM users WHERE name = $name AND email = $email'
26
26
  # dave = con.query(sql, name: 'Dave', email: 'dave@example.com')
27
27
  #
28
- def query(sql, *args, **hash)
29
- return query_sql(sql) if args.empty? && hash.empty?
28
+ def query(sql, *args, **kwargs)
29
+ return query_sql(sql) if args.empty? && kwargs.empty?
30
30
 
31
31
  stmt = PreparedStatement.new(self, sql)
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)
37
- end
32
+ stmt.bind_args(*args, **kwargs)
38
33
  stmt.execute
39
34
  end
40
35
 
36
+ #
37
+ # executes sql with args asynchronously.
38
+ # The first argument sql must be SQL string.
39
+ # The rest arguments are parameters of SQL string.
40
+ # This method returns DuckDB::PendingResult object.
41
+ #
42
+ # require 'duckdb'
43
+ # db = DuckDB::Database.open('duckdb_file')
44
+ # con = db.connect
45
+ # pending_result = con.async_query('SELECT * FROM users')
46
+ # sql = 'SELECT * FROM users WHERE name = ? AND email = ?'
47
+ # pending_result = con.async_query(sql, 'Dave', 'dave@example.com')
48
+ #
49
+ # # or You can use named parameter.
50
+ #
51
+ # sql = 'SELECT * FROM users WHERE name = $name AND email = $email'
52
+ # pending_result = con.async_query(sql, name: 'Dave', email: 'dave@example.com')
53
+ #
54
+ def async_query(sql, *args, **kwargs)
55
+ stmt = PreparedStatement.new(self, sql)
56
+ stmt.bind_args(*args, **kwargs)
57
+ stmt.pending_prepared
58
+ end
59
+
41
60
  #
42
61
  # connects DuckDB database
43
62
  # The first argument is DuckDB::Database object
@@ -83,6 +102,7 @@ module DuckDB
83
102
  end
84
103
 
85
104
  alias execute query
105
+ alias async_execute async_query
86
106
  alias open connect
87
107
  alias close disconnect
88
108
  end
@@ -42,6 +42,32 @@ module DuckDB
42
42
  "#{str[0, 8]}-#{str[8, 4]}-#{str[12, 4]}-#{str[16, 4]}-#{str[20, 12]}"
43
43
  end
44
44
 
45
+ def _parse_date(value)
46
+ case value
47
+ when Date, Time
48
+ value
49
+ else
50
+ begin
51
+ Date.parse(value)
52
+ rescue StandardError => e
53
+ raise(ArgumentError, "Cannot parse `#{value.inspect}` to Date object. #{e.message}")
54
+ end
55
+ end
56
+ end
57
+
58
+ def _parse_time(value)
59
+ case value
60
+ when Time
61
+ value
62
+ else
63
+ begin
64
+ Time.parse(value)
65
+ rescue StandardError => e
66
+ raise(ArgumentError, "Cannot parse `#{value.inspect}` to Time object. #{e.message}")
67
+ end
68
+ end
69
+ end
70
+
45
71
  private
46
72
 
47
73
  def integer_to_hugeint(value)
@@ -51,7 +77,7 @@ module DuckDB
51
77
  lower = value - (upper << HALF_HUGEINT_BIT)
52
78
  [lower, upper]
53
79
  else
54
- raise(ArgumentError, "The argument `#{value}` must be Integer.")
80
+ raise(ArgumentError, "The argument `#{value.inspect}` must be Integer.")
55
81
  end
56
82
  end
57
83
  end
@@ -1,3 +1,3 @@
1
1
  module DuckDB
2
- LIBRARY_VERSION = library_version[1..] if defined? library_version
2
+ LIBRARY_VERSION = library_version[1..]
3
3
  end
@@ -0,0 +1,39 @@
1
+ module DuckDB
2
+ # The DuckDB::PendingResult encapsulates connection with DuckDB pending
3
+ # result.
4
+ # PendingResult provides methods to execute SQL asynchronousely and check
5
+ # if the result is ready and to get the result.
6
+ #
7
+ # require 'duckdb'
8
+ #
9
+ # DuckDB::Result.use_chunk_each = true
10
+ #
11
+ # db = DuckDB::Database.open
12
+ # con = db.connect
13
+ # stmt = con.prepared_statement(VERY_SLOW_QUERY)
14
+ # pending_result = stmt.pending_prepared
15
+ # while pending_result.state == :not_ready
16
+ # print '.'
17
+ # sleep(0.01)
18
+ # pending_result.execute_task
19
+ # end
20
+ # result = pending_result.execute_pending
21
+ class PendingResult
22
+ STATES = %i[ready not_ready error no_tasks].freeze
23
+
24
+ # returns the state of the pending result.
25
+ # The result can be :ready, :not_ready, :error, :no_tasks.
26
+ # (:no_tasks is available only with duckdb 0.9.0 or later.)
27
+ #
28
+ # :ready means the result is ready to be fetched, and
29
+ # you can call `execute_pending` to get the result.
30
+ #
31
+ # :not_ready means the result is not ready yet, so
32
+ # you need to call `execute_task`.
33
+ #
34
+ # @return [Symbol] :ready, :not_ready, :error, :no_tasks
35
+ def state
36
+ STATES[_state]
37
+ end
38
+ end
39
+ end
@@ -20,21 +20,47 @@ module DuckDB
20
20
  RANGE_INT32 = -2_147_483_648..2_147_483_647
21
21
  RANGE_INT64 = -9_223_372_036_854_775_808..9_223_372_036_854_775_807
22
22
 
23
+ def pending_prepared
24
+ PendingResult.new(self)
25
+ end
26
+
27
+ # binds all parameters with SQL prepared statement.
28
+ #
29
+ # require 'duckdb'
30
+ # db = DuckDB::Database.open('duckdb_database')
31
+ # con = db.connect
32
+ # sql ='SELECT name FROM users WHERE id = ?'
33
+ # # or
34
+ # # sql ='SELECT name FROM users WHERE id = $id'
35
+ # stmt = PreparedStatement.new(con, sql)
36
+ # stmt.bind_args([1])
37
+ # # or
38
+ # # stmt.bind_args(id: 1)
39
+ def bind_args(*args, **kwargs)
40
+ args.each.with_index(1) do |arg, i|
41
+ bind(i, arg)
42
+ end
43
+ kwargs.each do |key, value|
44
+ bind(key, value)
45
+ end
46
+ end
47
+
23
48
  # binds i-th parameter with SQL prepared statement.
24
49
  # The first argument is index of parameter.
25
50
  # The index of first parameter is 1 not 0.
26
51
  # The second argument value is to expected Integer value.
27
52
  # This method uses bind_varchar internally.
53
+ #
28
54
  # require 'duckdb'
29
55
  # db = DuckDB::Database.open('duckdb_database')
30
56
  # con = db.connect
31
57
  # sql ='SELECT name FROM users WHERE bigint_col = ?'
32
58
  # stmt = PreparedStatement.new(con, sql)
33
59
  # stmt.bind_hugeint(1, 1_234_567_890_123_456_789_012_345)
34
- def bind_hugeint(i, value)
60
+ def bind_hugeint(index, value)
35
61
  case value
36
62
  when Integer
37
- bind_varchar(i, value.to_s)
63
+ bind_varchar(index, value.to_s)
38
64
  else
39
65
  raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
40
66
  end
@@ -45,6 +71,7 @@ module DuckDB
45
71
  # The index of first parameter is 1 not 0.
46
72
  # The second argument value must be Integer value.
47
73
  # This method uses duckdb_bind_hugeint internally.
74
+ #
48
75
  # require 'duckdb'
49
76
  # db = DuckDB::Database.open('duckdb_database')
50
77
  # con = db.connect
@@ -69,19 +96,10 @@ module DuckDB
69
96
  # stmt.bind(1, Date.today)
70
97
  # # or you can specify date string.
71
98
  # # stmt.bind(1, '2021-02-23')
72
- def bind_date(i, value)
73
- case value
74
- when Date, Time
75
- date = value
76
- else
77
- begin
78
- date = Date.parse(value)
79
- rescue => e
80
- raise(ArgumentError, "Cannot parse argument value to date. #{e.message}")
81
- end
82
- end
99
+ def bind_date(index, value)
100
+ date = _parse_date(value)
83
101
 
84
- _bind_date(i, date.year, date.month, date.day)
102
+ _bind_date(index, date.year, date.month, date.day)
85
103
  end
86
104
 
87
105
  # binds i-th parameter with SQL prepared statement.
@@ -97,19 +115,10 @@ module DuckDB
97
115
  # stmt.bind(1, Time.now)
98
116
  # # or you can specify time string.
99
117
  # # stmt.bind(1, '07:39:45')
100
- def bind_time(i, value)
101
- case value
102
- when Time
103
- time = value
104
- else
105
- begin
106
- time = Time.parse(value)
107
- rescue => e
108
- raise(ArgumentError, "Cannot parse argument value to time. #{e.message}")
109
- end
110
- end
118
+ def bind_time(index, value)
119
+ time = _parse_time(value)
111
120
 
112
- _bind_time(i, time.hour, time.min, time.sec, time.usec)
121
+ _bind_time(index, time.hour, time.min, time.sec, time.usec)
113
122
  end
114
123
 
115
124
  # binds i-th parameter with SQL prepared statement.
@@ -125,19 +134,10 @@ module DuckDB
125
134
  # stmt.bind(1, Time.now)
126
135
  # # or you can specify timestamp string.
127
136
  # # stmt.bind(1, '2022-02-23 07:39:45')
128
- def bind_timestamp(i, value)
129
- case value
130
- when Time
131
- time = value
132
- else
133
- begin
134
- time = Time.parse(value)
135
- rescue => e
136
- raise(ArgumentError, "Cannot parse argument value to time. #{e.message}")
137
- end
138
- end
137
+ def bind_timestamp(index, value)
138
+ time = _parse_time(value)
139
139
 
140
- _bind_timestamp(i, time.year, time.month, time.day, time.hour, time.min, time.sec, time.usec)
140
+ _bind_timestamp(index, time.year, time.month, time.day, time.hour, time.min, time.sec, time.usec)
141
141
  end
142
142
 
143
143
  # binds i-th parameter with SQL prepared statement.
@@ -151,9 +151,9 @@ module DuckDB
151
151
  # sql ='SELECT value FROM intervals WHERE interval = ?'
152
152
  # stmt = PreparedStatement.new(con, sql)
153
153
  # stmt.bind(1, 'P1Y2D')
154
- def bind_interval(i, value)
154
+ def bind_interval(index, value)
155
155
  value = Interval.to_interval(value)
156
- _bind_interval(i, value.interval_months, value.interval_days, value.interval_micros)
156
+ _bind_interval(index, value.interval_months, value.interval_days, value.interval_micros)
157
157
  end
158
158
 
159
159
  # binds i-th parameter with SQL prepared statement.
data/lib/duckdb/result.rb CHANGED
@@ -25,7 +25,7 @@ module DuckDB
25
25
  class Result
26
26
  include Enumerable
27
27
 
28
- ToRuby = {
28
+ TO_METHODS = Hash.new(:_to_string).merge(
29
29
  1 => :_to_boolean,
30
30
  3 => :_to_smallint,
31
31
  4 => :_to_integer,
@@ -35,21 +35,25 @@ module DuckDB
35
35
  16 => :_to_hugeint_internal,
36
36
  18 => :_to_blob,
37
37
  19 => :_to_decimal_internal
38
- }
39
-
40
- ToRuby.default = :_to_string
38
+ ).freeze
41
39
 
42
40
  alias column_size column_count
43
41
  alias row_size row_count
44
42
 
45
- def self.use_chunk_each=(val)
46
- raise DuckDB::Error, 'chunk_each is not available. Install duckdb >= 0.8.0 and rerun `gem install duckdb`.' unless instance_methods.include?(:chunk_each)
43
+ class << self
44
+ def new
45
+ raise DuckDB::Error, 'DuckDB::Result cannot be instantiated directly.'
46
+ end
47
47
 
48
- @use_chunk_each = val
49
- end
48
+ def use_chunk_each=(val)
49
+ raise DuckDB::Error, 'chunk_each is not available. Install duckdb >= 0.8.0 and rerun `gem install duckdb`.' unless instance_methods.include?(:chunk_each)
50
50
 
51
- def self.use_chunk_each?
52
- !!@use_chunk_each
51
+ @use_chunk_each = val
52
+ end
53
+
54
+ def use_chunk_each?
55
+ !!@use_chunk_each
56
+ end
53
57
  end
54
58
 
55
59
  def each
@@ -58,7 +62,7 @@ module DuckDB
58
62
 
59
63
  chunk_each { |row| yield row }
60
64
  else
61
- warn('this `each` behavior will be deprecated in the future. set `Result.use_chunk_each = true` to use new `each` behavior.')
65
+ warn('this `each` behavior will be deprecated in the future. set `DuckDB::Result.use_chunk_each = true` to use new `each` behavior.')
62
66
  return to_enum { row_size } unless block_given?
63
67
 
64
68
  row_count.times do |row_index|
@@ -76,7 +80,7 @@ module DuckDB
76
80
  end
77
81
 
78
82
  def to_value(row_index, col_index)
79
- send(ToRuby[_column_type(col_index)], row_index, col_index)
83
+ send(TO_METHODS[_column_type(col_index)], row_index, col_index)
80
84
  end
81
85
 
82
86
  def enum_dictionary_values(col_index)
@@ -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.1'
6
+ VERSION = '0.9.1.2'
7
7
  end
data/lib/duckdb.rb CHANGED
@@ -8,6 +8,7 @@ require 'duckdb/database'
8
8
  require 'duckdb/connection'
9
9
  require 'duckdb/result'
10
10
  require 'duckdb/prepared_statement'
11
+ require 'duckdb/pending_result'
11
12
  require 'duckdb/appender'
12
13
  require 'duckdb/config'
13
14
  require 'duckdb/column'
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.1
4
+ version: 0.9.1.2
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-10-14 00:00:00.000000000 Z
11
+ date: 2023-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,6 +115,8 @@ files:
115
115
  - ext/duckdb/error.c
116
116
  - ext/duckdb/error.h
117
117
  - ext/duckdb/extconf.rb
118
+ - ext/duckdb/pending_result.c
119
+ - ext/duckdb/pending_result.h
118
120
  - ext/duckdb/prepared_statement.c
119
121
  - ext/duckdb/prepared_statement.h
120
122
  - ext/duckdb/result.c
@@ -132,6 +134,7 @@ files:
132
134
  - lib/duckdb/database.rb
133
135
  - lib/duckdb/interval.rb
134
136
  - lib/duckdb/library_version.rb
137
+ - lib/duckdb/pending_result.rb
135
138
  - lib/duckdb/prepared_statement.rb
136
139
  - lib/duckdb/result.rb
137
140
  - lib/duckdb/version.rb