duckdb 0.9.1.1 → 0.9.2

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