duckdb 0.9.1 → 0.9.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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