duckdb 0.9.1.1 → 0.9.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test_on_macos.yml +6 -6
  4. data/.github/workflows/test_on_ubuntu.yml +6 -6
  5. data/.github/workflows/test_on_windows.yml +4 -4
  6. data/CHANGELOG.md +11 -0
  7. data/Dockerfile +1 -1
  8. data/Gemfile.lock +5 -5
  9. data/README.md +17 -1
  10. data/benchmark/async_query.rb +90 -0
  11. data/ext/duckdb/appender.c +5 -5
  12. data/ext/duckdb/appender.h +1 -1
  13. data/ext/duckdb/blob.c +1 -1
  14. data/ext/duckdb/blob.h +1 -4
  15. data/ext/duckdb/column.c +2 -2
  16. data/ext/duckdb/column.h +2 -2
  17. data/ext/duckdb/config.c +1 -1
  18. data/ext/duckdb/config.h +1 -1
  19. data/ext/duckdb/connection.c +66 -6
  20. data/ext/duckdb/connection.h +2 -2
  21. data/ext/duckdb/converter.h +1 -1
  22. data/ext/duckdb/conveter.c +1 -1
  23. data/ext/duckdb/database.c +3 -3
  24. data/ext/duckdb/database.h +2 -2
  25. data/ext/duckdb/duckdb.c +11 -11
  26. data/ext/duckdb/error.c +1 -1
  27. data/ext/duckdb/error.h +1 -1
  28. data/ext/duckdb/extconf.rb +46 -13
  29. data/ext/duckdb/pending_result.c +45 -6
  30. data/ext/duckdb/pending_result.h +1 -1
  31. data/ext/duckdb/prepared_statement.c +7 -7
  32. data/ext/duckdb/prepared_statement.h +1 -1
  33. data/ext/duckdb/result.c +112 -70
  34. data/ext/duckdb/result.h +2 -2
  35. data/ext/duckdb/ruby-duckdb.h +1 -0
  36. data/ext/duckdb/util.c +4 -4
  37. data/ext/duckdb/util.h +4 -4
  38. data/lib/duckdb/appender.rb +1 -10
  39. data/lib/duckdb/connection.rb +50 -8
  40. data/lib/duckdb/converter.rb +27 -1
  41. data/lib/duckdb/prepared_statement.rb +42 -40
  42. data/lib/duckdb/result.rb +8 -2
  43. data/lib/duckdb/version.rb +1 -1
  44. data/sample/async_query.rb +24 -0
  45. data/sample/async_query_stream.rb +24 -0
  46. metadata +6 -2
@@ -1,31 +1,64 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'mkmf'
2
4
 
3
- def duckdb_library_available?(func)
4
- header = find_header('duckdb.h') || find_header('duckdb.h', '/opt/homebrew/include')
5
- library = have_func(func, 'duckdb.h') || find_library('duckdb', func, '/opt/homebrew/opt/duckdb/lib')
6
- header && library
5
+ DUCKDB_REQUIRED_VERSION = '0.8.0'
6
+
7
+ def check_duckdb_header(header, version)
8
+ found = find_header(
9
+ header,
10
+ '/opt/homebrew/include',
11
+ '/opt/homebrew/opt/duckdb/include',
12
+ '/opt/local/include'
13
+ )
14
+ return if found
15
+
16
+ msg = "#{header} is not found. Install #{header} of duckdb >= #{version}."
17
+ print_message(msg)
18
+ raise msg
7
19
  end
8
20
 
9
- def check_duckdb_library(func, version)
10
- return if duckdb_library_available?(func)
21
+ def check_duckdb_library(library, func, version)
22
+ found = find_library(
23
+ library,
24
+ func,
25
+ '/opt/homebrew/lib',
26
+ '/opt/homebrew/opt/duckdb/lib',
27
+ '/opt/local/lib'
28
+ )
29
+ return if found
11
30
 
12
- msg = "duckdb >= #{version} is not found. Install duckdb >= #{version} library and header file."
13
- puts ''
14
- puts '*' * 80
15
- puts msg
16
- puts '*' * 80
17
- puts ''
31
+ library_name = duckdb_library_name(library)
32
+ msg = "#{library_name} is not found. Install #{library_name} of duckdb >= #{version}."
33
+ print_message(msg)
18
34
  raise msg
19
35
  end
20
36
 
37
+ def duckdb_library_name(library)
38
+ "lib#{library}.(so|dylib|dll)"
39
+ end
40
+
41
+ def print_message(msg)
42
+ print <<~END_OF_MESSAGE
43
+
44
+ #{'*' * 80}
45
+ #{msg}
46
+ #{'*' * 80}
47
+
48
+ END_OF_MESSAGE
49
+ end
50
+
21
51
  dir_config('duckdb')
22
52
 
53
+ check_duckdb_header('duckdb.h', DUCKDB_REQUIRED_VERSION)
54
+
23
55
  # check duckdb >= 0.8.0
24
- check_duckdb_library('duckdb_string_is_inlined', '0.8.0')
56
+ check_duckdb_library('duckdb', 'duckdb_string_is_inlined', DUCKDB_REQUIRED_VERSION)
25
57
 
26
58
  # check duckdb >= 0.9.0
27
59
  have_func('duckdb_bind_parameter_index', 'duckdb.h')
28
60
 
61
+ # duckdb_parameter_name is not found on Windows.
29
62
  have_func('duckdb_parameter_name', 'duckdb.h')
30
63
 
31
64
  create_makefile('duckdb/duckdb_native')
@@ -5,7 +5,7 @@ static VALUE cDuckDBPendingResult;
5
5
  static void deallocate(void *ctx);
6
6
  static VALUE allocate(VALUE klass);
7
7
  static size_t memsize(const void *p);
8
- static VALUE duckdb_pending_result_initialize(VALUE self, VALUE oDuckDBPreparedStatement);
8
+ static VALUE duckdb_pending_result_initialize(int argc, VALUE *args, VALUE self);
9
9
  static VALUE duckdb_pending_result_execute_task(VALUE self);
10
10
  static VALUE duckdb_pending_result_execute_pending(VALUE self);
11
11
 
@@ -38,16 +38,43 @@ static size_t memsize(const void *p) {
38
38
  return sizeof(rubyDuckDBPendingResult);
39
39
  }
40
40
 
41
- static VALUE duckdb_pending_result_initialize(VALUE self, VALUE oDuckDBPreparedStatement) {
41
+ static VALUE duckdb_pending_result_initialize(int argc, VALUE *argv, VALUE self) {
42
+ VALUE oDuckDBPreparedStatement;
43
+ VALUE streaming_p = Qfalse;
44
+ duckdb_state state;
45
+
46
+ rb_scan_args(argc, argv, "11", &oDuckDBPreparedStatement, &streaming_p);
47
+
48
+ if (rb_obj_is_kind_of(oDuckDBPreparedStatement, cDuckDBPreparedStatement) != Qtrue) {
49
+ rb_raise(rb_eTypeError, "1st argument must be DuckDB::PreparedStatement");
50
+ }
51
+
42
52
  rubyDuckDBPendingResult *ctx = get_struct_pending_result(self);
43
53
  rubyDuckDBPreparedStatement *stmt = get_struct_prepared_statement(oDuckDBPreparedStatement);
44
54
 
45
- if (duckdb_pending_prepared(stmt->prepared_statement, &(ctx->pending_result)) == DuckDBError) {
55
+ if (!NIL_P(streaming_p) && streaming_p == Qtrue) {
56
+ state = duckdb_pending_prepared_streaming(stmt->prepared_statement, &(ctx->pending_result));
57
+ } else {
58
+ state = duckdb_pending_prepared(stmt->prepared_statement, &(ctx->pending_result));
59
+ }
60
+
61
+ if (state == DuckDBError) {
46
62
  rb_raise(eDuckDBError, "%s", duckdb_pending_error(ctx->pending_result));
47
63
  }
48
64
  return self;
49
65
  }
50
66
 
67
+ /*
68
+ * call-seq:
69
+ * pending_result.execute_task -> nil
70
+ *
71
+ * Executes the task in the pending result.
72
+ *
73
+ * db = DuckDB::Database.open
74
+ * conn = db.connect
75
+ * pending_result = conn.async_query("slow query")
76
+ * pending_result.execute_task
77
+ */
51
78
  static VALUE duckdb_pending_result_execute_task(VALUE self) {
52
79
  rubyDuckDBPendingResult *ctx = get_struct_pending_result(self);
53
80
  ctx->state = duckdb_pending_execute_task(ctx->pending_result);
@@ -61,10 +88,22 @@ static VALUE duckdb_pending_result_execution_finished_p(VALUE self) {
61
88
  }
62
89
  #endif
63
90
 
91
+ /*
92
+ * call-seq:
93
+ * pending_result.execute_pending -> DuckDB::Result
94
+ *
95
+ * Get DuckDB::Result object after query execution finished.
96
+ *
97
+ * db = DuckDB::Database.open
98
+ * conn = db.connect
99
+ * pending_result = conn.async_query("slow query")
100
+ * pending_result.execute_task while pending_result.state != :ready
101
+ * result = pending_result.execute_pending # => DuckDB::Result
102
+ */
64
103
  static VALUE duckdb_pending_result_execute_pending(VALUE self) {
65
104
  rubyDuckDBPendingResult *ctx;
66
105
  rubyDuckDBResult *ctxr;
67
- VALUE result = create_result();
106
+ VALUE result = rbduckdb_create_result();
68
107
 
69
108
  TypedData_Get_Struct(self, rubyDuckDBPendingResult, &pending_result_data_type, ctx);
70
109
  ctxr = get_struct_result(result);
@@ -85,11 +124,11 @@ rubyDuckDBPendingResult *get_struct_pending_result(VALUE obj) {
85
124
  return ctx;
86
125
  }
87
126
 
88
- void init_duckdb_pending_result(void) {
127
+ void rbduckdb_init_duckdb_pending_result(void) {
89
128
  cDuckDBPendingResult = rb_define_class_under(mDuckDB, "PendingResult", rb_cObject);
90
129
  rb_define_alloc_func(cDuckDBPendingResult, allocate);
91
130
 
92
- rb_define_method(cDuckDBPendingResult, "initialize", duckdb_pending_result_initialize, 1);
131
+ rb_define_method(cDuckDBPendingResult, "initialize", duckdb_pending_result_initialize, -1);
93
132
  rb_define_method(cDuckDBPendingResult, "execute_task", duckdb_pending_result_execute_task, 0);
94
133
  rb_define_method(cDuckDBPendingResult, "execute_pending", duckdb_pending_result_execute_pending, 0);
95
134
 
@@ -9,5 +9,5 @@ struct _rubyDuckDBPendingResult {
9
9
  typedef struct _rubyDuckDBPendingResult rubyDuckDBPendingResult;
10
10
 
11
11
  rubyDuckDBPendingResult *get_struct_pending_result(VALUE obj);
12
- void init_duckdb_pending_result(void);
12
+ void rbduckdb_init_duckdb_pending_result(void);
13
13
  #endif
@@ -1,6 +1,6 @@
1
1
  #include "ruby-duckdb.h"
2
2
 
3
- static VALUE cDuckDBPreparedStatement;
3
+ VALUE cDuckDBPreparedStatement;
4
4
 
5
5
  static void deallocate(void *ctx);
6
6
  static VALUE allocate(VALUE klass);
@@ -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);
@@ -347,7 +347,7 @@ rubyDuckDBPreparedStatement *get_struct_prepared_statement(VALUE self) {
347
347
  return ctx;
348
348
  }
349
349
 
350
- void init_duckdb_prepared_statement(void) {
350
+ void rbduckdb_init_duckdb_prepared_statement(void) {
351
351
  cDuckDBPreparedStatement = rb_define_class_under(mDuckDB, "PreparedStatement", rb_cObject);
352
352
 
353
353
  rb_define_alloc_func(cDuckDBPreparedStatement, allocate);
@@ -9,6 +9,6 @@ struct _rubyDuckDBPreparedStatement {
9
9
  typedef struct _rubyDuckDBPreparedStatement rubyDuckDBPreparedStatement;
10
10
 
11
11
  rubyDuckDBPreparedStatement *get_struct_prepared_statement(VALUE self);
12
- void init_duckdb_prepared_statement(void);
12
+ void rbduckdb_init_duckdb_prepared_statement(void);
13
13
 
14
14
  #endif
data/ext/duckdb/result.c CHANGED
@@ -19,6 +19,11 @@ static VALUE duckdb_result_column_count(VALUE oDuckDBResult);
19
19
  static VALUE duckdb_result_row_count(VALUE oDuckDBResult);
20
20
  static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult);
21
21
  static VALUE duckdb_result_columns(VALUE oDuckDBResult);
22
+ static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult);
23
+ static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult);
24
+
25
+ static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult);
26
+ static void yield_rows(duckdb_data_chunk chunk, idx_t col_count);
22
27
  static VALUE duckdb_result__column_type(VALUE oDuckDBResult, VALUE col_idx);
23
28
  static VALUE duckdb_result__is_null(VALUE oDuckDBResult, VALUE row_idx, VALUE col_idx);
24
29
  static VALUE duckdb_result__to_boolean(VALUE oDuckDBResult, VALUE row_idx, VALUE col_idx);
@@ -50,7 +55,6 @@ static VALUE vector_map(duckdb_logical_type ty, duckdb_vector vector, idx_t row_
50
55
  static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t row_idx);
51
56
  static VALUE vector_uuid(void* vector_data, idx_t row_idx);
52
57
  static VALUE vector_value(duckdb_vector vector, idx_t row_idx);
53
- static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult);
54
58
 
55
59
  static const rb_data_type_t result_data_type = {
56
60
  "DuckDB/Result",
@@ -229,12 +233,85 @@ static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
229
233
 
230
234
  VALUE ary = rb_ary_new2(column_count);
231
235
  for(col_idx = 0; col_idx < column_count; col_idx++) {
232
- VALUE column = create_column(oDuckDBResult, col_idx);
236
+ VALUE column = rbduckdb_create_column(oDuckDBResult, col_idx);
233
237
  rb_ary_store(ary, col_idx, column);
234
238
  }
235
239
  return ary;
236
240
  }
237
241
 
242
+ /*
243
+ * call-seq:
244
+ * result.streaming? -> Boolean
245
+ *
246
+ * Returns true if the result is streaming, otherwise false.
247
+ *
248
+ */
249
+ static VALUE duckdb_result_streaming_p(VALUE oDuckDBResult) {
250
+ rubyDuckDBResult *ctx;
251
+ TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
252
+ return duckdb_result_is_streaming(ctx->result) ? Qtrue : Qfalse;
253
+ }
254
+
255
+ static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult) {
256
+ rubyDuckDBResult *ctx;
257
+ idx_t col_count;
258
+ idx_t chunk_count;
259
+ idx_t chunk_idx;
260
+ duckdb_data_chunk chunk;
261
+
262
+ TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
263
+
264
+ col_count = duckdb_column_count(&(ctx->result));
265
+ chunk_count = duckdb_result_chunk_count(ctx->result);
266
+
267
+ RETURN_ENUMERATOR(oDuckDBResult, 0, 0);
268
+
269
+ for (chunk_idx = 0; chunk_idx < chunk_count; chunk_idx++) {
270
+ chunk = duckdb_result_get_chunk(ctx->result, chunk_idx);
271
+ yield_rows(chunk, col_count);
272
+ duckdb_destroy_data_chunk(&chunk);
273
+ }
274
+ return Qnil;
275
+ }
276
+
277
+ static VALUE duckdb_result__chunk_stream(VALUE oDuckDBResult) {
278
+ rubyDuckDBResult *ctx;
279
+ duckdb_data_chunk chunk;
280
+ idx_t col_count;
281
+
282
+ TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
283
+
284
+ RETURN_ENUMERATOR(oDuckDBResult, 0, 0);
285
+
286
+ col_count = duckdb_column_count(&(ctx->result));
287
+
288
+ while((chunk = duckdb_stream_fetch_chunk(ctx->result)) != NULL) {
289
+ yield_rows(chunk, col_count);
290
+ duckdb_destroy_data_chunk(&chunk);
291
+ }
292
+ return Qnil;
293
+ }
294
+
295
+ static void yield_rows(duckdb_data_chunk chunk, idx_t col_count) {
296
+ idx_t row_count;
297
+ idx_t row_idx;
298
+ idx_t col_idx;
299
+ duckdb_vector vector;
300
+ VALUE row;
301
+ VALUE val;
302
+
303
+ row_count = duckdb_data_chunk_get_size(chunk);
304
+ for (row_idx = 0; row_idx < row_count; row_idx++) {
305
+ row = rb_ary_new2(col_count);
306
+ for (col_idx = 0; col_idx < col_count; col_idx++) {
307
+ vector = duckdb_data_chunk_get_vector(chunk, col_idx);
308
+ val = vector_value(vector, row_idx);
309
+ rb_ary_store(row, col_idx, val);
310
+ }
311
+ rb_yield(row);
312
+ }
313
+ }
314
+
238
315
  static VALUE duckdb_result__column_type(VALUE oDuckDBResult, VALUE col_idx) {
239
316
  rubyDuckDBResult *ctx;
240
317
  TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
@@ -397,7 +474,7 @@ static VALUE duckdb_result__enum_dictionary_value(VALUE oDuckDBResult, VALUE col
397
474
  return value;
398
475
  }
399
476
 
400
- VALUE create_result(void) {
477
+ VALUE rbduckdb_create_result(void) {
401
478
  return allocate(cDuckDBResult);
402
479
  }
403
480
 
@@ -405,32 +482,32 @@ static VALUE vector_date(void *vector_data, idx_t row_idx) {
405
482
  duckdb_date_struct date = duckdb_from_date(((duckdb_date *) vector_data)[row_idx]);
406
483
 
407
484
  return rb_funcall(mDuckDBConverter, rb_intern("_to_date"), 3,
408
- INT2FIX(date.year),
409
- INT2FIX(date.month),
410
- INT2FIX(date.day)
411
- );
485
+ INT2FIX(date.year),
486
+ INT2FIX(date.month),
487
+ INT2FIX(date.day)
488
+ );
412
489
  }
413
490
 
414
491
  static VALUE vector_timestamp(void* vector_data, idx_t row_idx) {
415
492
  duckdb_timestamp_struct data = duckdb_from_timestamp(((duckdb_timestamp *)vector_data)[row_idx]);
416
493
  return rb_funcall(mDuckDBConverter, rb_intern("_to_time"), 7,
417
- INT2FIX(data.date.year),
418
- INT2FIX(data.date.month),
419
- INT2FIX(data.date.day),
420
- INT2FIX(data.time.hour),
421
- INT2FIX(data.time.min),
422
- INT2FIX(data.time.sec),
423
- INT2NUM(data.time.micros)
424
- );
494
+ INT2FIX(data.date.year),
495
+ INT2FIX(data.date.month),
496
+ INT2FIX(data.date.day),
497
+ INT2FIX(data.time.hour),
498
+ INT2FIX(data.time.min),
499
+ INT2FIX(data.time.sec),
500
+ INT2NUM(data.time.micros)
501
+ );
425
502
  }
426
503
 
427
504
  static VALUE vector_interval(void* vector_data, idx_t row_idx) {
428
505
  duckdb_interval data = ((duckdb_interval *)vector_data)[row_idx];
429
506
  return rb_funcall(mDuckDBConverter, rb_intern("_to_interval_from_vector"), 3,
430
- INT2NUM(data.months),
431
- INT2NUM(data.days),
432
- LL2NUM(data.micros)
433
- );
507
+ INT2NUM(data.months),
508
+ INT2NUM(data.days),
509
+ LL2NUM(data.micros)
510
+ );
434
511
  }
435
512
 
436
513
  static VALUE vector_blob(void* vector_data, idx_t row_idx) {
@@ -454,9 +531,9 @@ static VALUE vector_varchar(void* vector_data, idx_t row_idx) {
454
531
  static VALUE vector_hugeint(void* vector_data, idx_t row_idx) {
455
532
  duckdb_hugeint hugeint = ((duckdb_hugeint *)vector_data)[row_idx];
456
533
  return rb_funcall(mDuckDBConverter, rb_intern("_to_hugeint_from_vector"), 2,
457
- ULL2NUM(hugeint.lower),
458
- LL2NUM(hugeint.upper)
459
- );
534
+ ULL2NUM(hugeint.lower),
535
+ LL2NUM(hugeint.upper)
536
+ );
460
537
  }
461
538
 
462
539
  static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row_idx) {
@@ -477,11 +554,11 @@ static VALUE vector_decimal(duckdb_logical_type ty, void* vector_data, idx_t row
477
554
  }
478
555
 
479
556
  return rb_funcall(mDuckDBConverter, rb_intern("_to_decimal_from_vector"), 4,
480
- INT2FIX(width),
481
- INT2FIX(scale),
482
- ULL2NUM(value.lower),
483
- LL2NUM(value.upper)
484
- );
557
+ INT2FIX(width),
558
+ INT2FIX(scale),
559
+ ULL2NUM(value.lower),
560
+ LL2NUM(value.upper)
561
+ );
485
562
  }
486
563
 
487
564
  static VALUE vector_enum(duckdb_logical_type ty, void* vector_data, idx_t row_idx) {
@@ -577,9 +654,9 @@ static VALUE vector_struct(duckdb_logical_type ty, duckdb_vector vector, idx_t r
577
654
  static VALUE vector_uuid(void* vector_data, idx_t row_idx) {
578
655
  duckdb_hugeint hugeint = ((duckdb_hugeint *)vector_data)[row_idx];
579
656
  return rb_funcall(mDuckDBConverter, rb_intern("_to_uuid_from_vector"), 2,
580
- ULL2NUM(hugeint.lower),
581
- LL2NUM(hugeint.upper)
582
- );
657
+ ULL2NUM(hugeint.lower),
658
+ LL2NUM(hugeint.upper)
659
+ );
583
660
  }
584
661
 
585
662
  static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
@@ -617,7 +694,7 @@ static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
617
694
  case DUCKDB_TYPE_BIGINT:
618
695
  obj = LL2NUM(((int64_t *) vector_data)[row_idx]);
619
696
  break;
620
- case DUCKDB_TYPE_UTINYINT:
697
+ case DUCKDB_TYPE_UTINYINT:
621
698
  obj = INT2FIX(((uint8_t *) vector_data)[row_idx]);
622
699
  break;
623
700
  case DUCKDB_TYPE_USMALLINT:
@@ -680,44 +757,7 @@ static VALUE vector_value(duckdb_vector vector, idx_t row_idx) {
680
757
  return obj;
681
758
  }
682
759
 
683
- static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult) {
684
- rubyDuckDBResult *ctx;
685
- VALUE row;
686
- idx_t col_count;
687
- idx_t row_count;
688
- idx_t chunk_count;
689
- idx_t col_idx;
690
- idx_t row_idx;
691
- idx_t chunk_idx;
692
- duckdb_data_chunk chunk;
693
- duckdb_vector vector;
694
- VALUE val;
695
-
696
- TypedData_Get_Struct(oDuckDBResult, rubyDuckDBResult, &result_data_type, ctx);
697
-
698
- col_count = duckdb_column_count(&(ctx->result));
699
- chunk_count = duckdb_result_chunk_count(ctx->result);
700
-
701
- RETURN_ENUMERATOR(oDuckDBResult, 0, 0);
702
-
703
- for (chunk_idx = 0; chunk_idx < chunk_count; chunk_idx++) {
704
- chunk = duckdb_result_get_chunk(ctx->result, chunk_idx);
705
- row_count = duckdb_data_chunk_get_size(chunk);
706
- for (row_idx = 0; row_idx < row_count; row_idx++) {
707
- row = rb_ary_new2(col_count);
708
- for (col_idx = 0; col_idx < col_count; col_idx++) {
709
- vector = duckdb_data_chunk_get_vector(chunk, col_idx);
710
- val = vector_value(vector, row_idx);
711
- rb_ary_store(row, col_idx, val);
712
- }
713
- rb_yield(row);
714
- }
715
- duckdb_destroy_data_chunk(&chunk);
716
- }
717
- return Qnil;
718
- }
719
-
720
- void init_duckdb_result(void) {
760
+ void rbduckdb_init_duckdb_result(void) {
721
761
  cDuckDBResult = rb_define_class_under(mDuckDB, "Result", rb_cObject);
722
762
  rb_define_alloc_func(cDuckDBResult, allocate);
723
763
 
@@ -725,6 +765,9 @@ void init_duckdb_result(void) {
725
765
  rb_define_method(cDuckDBResult, "row_count", duckdb_result_row_count, 0);
726
766
  rb_define_method(cDuckDBResult, "rows_changed", duckdb_result_rows_changed, 0);
727
767
  rb_define_method(cDuckDBResult, "columns", duckdb_result_columns, 0);
768
+ rb_define_method(cDuckDBResult, "streaming?", duckdb_result_streaming_p, 0);
769
+ rb_define_method(cDuckDBResult, "chunk_each", duckdb_result_chunk_each, 0);
770
+ rb_define_private_method(cDuckDBResult, "_chunk_stream", duckdb_result__chunk_stream, 0);
728
771
  rb_define_private_method(cDuckDBResult, "_column_type", duckdb_result__column_type, 1);
729
772
  rb_define_private_method(cDuckDBResult, "_null?", duckdb_result__is_null, 2);
730
773
  rb_define_private_method(cDuckDBResult, "_to_boolean", duckdb_result__to_boolean, 2);
@@ -742,5 +785,4 @@ void init_duckdb_result(void) {
742
785
  rb_define_private_method(cDuckDBResult, "_enum_internal_type", duckdb_result__enum_internal_type, 1);
743
786
  rb_define_private_method(cDuckDBResult, "_enum_dictionary_size", duckdb_result__enum_dictionary_size, 1);
744
787
  rb_define_private_method(cDuckDBResult, "_enum_dictionary_value", duckdb_result__enum_dictionary_value, 2);
745
- rb_define_method(cDuckDBResult, "chunk_each", duckdb_result_chunk_each, 0);
746
788
  }
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
 
@@ -29,5 +29,6 @@ extern VALUE cDuckDBBlob;
29
29
  extern VALUE cDuckDBConfig;
30
30
  extern VALUE eDuckDBError;
31
31
  extern VALUE mDuckDBConverter;
32
+ extern VALUE cDuckDBPreparedStatement;
32
33
 
33
34
  #endif
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