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.
- checksums.yaml +4 -4
- data/.gitattributes +1 -0
- data/.github/workflows/test_on_macos.yml +6 -6
- data/.github/workflows/test_on_ubuntu.yml +6 -6
- data/.github/workflows/test_on_windows.yml +4 -4
- data/CHANGELOG.md +11 -0
- data/Dockerfile +1 -1
- data/Gemfile.lock +5 -5
- data/README.md +17 -1
- data/benchmark/async_query.rb +90 -0
- data/ext/duckdb/appender.c +5 -5
- data/ext/duckdb/appender.h +1 -1
- data/ext/duckdb/blob.c +1 -1
- data/ext/duckdb/blob.h +1 -4
- data/ext/duckdb/column.c +2 -2
- data/ext/duckdb/column.h +2 -2
- data/ext/duckdb/config.c +1 -1
- data/ext/duckdb/config.h +1 -1
- data/ext/duckdb/connection.c +66 -6
- data/ext/duckdb/connection.h +2 -2
- data/ext/duckdb/converter.h +1 -1
- data/ext/duckdb/conveter.c +1 -1
- data/ext/duckdb/database.c +3 -3
- data/ext/duckdb/database.h +2 -2
- data/ext/duckdb/duckdb.c +11 -11
- data/ext/duckdb/error.c +1 -1
- data/ext/duckdb/error.h +1 -1
- data/ext/duckdb/extconf.rb +46 -13
- data/ext/duckdb/pending_result.c +45 -6
- data/ext/duckdb/pending_result.h +1 -1
- data/ext/duckdb/prepared_statement.c +7 -7
- data/ext/duckdb/prepared_statement.h +1 -1
- data/ext/duckdb/result.c +112 -70
- data/ext/duckdb/result.h +2 -2
- data/ext/duckdb/ruby-duckdb.h +1 -0
- data/ext/duckdb/util.c +4 -4
- data/ext/duckdb/util.h +4 -4
- data/lib/duckdb/appender.rb +1 -10
- data/lib/duckdb/connection.rb +50 -8
- data/lib/duckdb/converter.rb +27 -1
- data/lib/duckdb/prepared_statement.rb +42 -40
- data/lib/duckdb/result.rb +8 -2
- data/lib/duckdb/version.rb +1 -1
- data/sample/async_query.rb +24 -0
- data/sample/async_query_stream.rb +24 -0
- metadata +6 -2
data/ext/duckdb/extconf.rb
CHANGED
@@ -1,31 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'mkmf'
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
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('
|
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')
|
data/ext/duckdb/pending_result.c
CHANGED
@@ -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
|
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
|
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 (
|
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 =
|
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
|
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
|
|
data/ext/duckdb/pending_result.h
CHANGED
@@ -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
|
12
|
+
void rbduckdb_init_duckdb_pending_result(void);
|
13
13
|
#endif
|
@@ -1,6 +1,6 @@
|
|
1
1
|
#include "ruby-duckdb.h"
|
2
2
|
|
3
|
-
|
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 =
|
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 =
|
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 =
|
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 =
|
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
|
-
|
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
|
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
|
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 =
|
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
|
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
|
-
|
409
|
-
|
410
|
-
|
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
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
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
|
-
|
431
|
-
|
432
|
-
|
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
|
-
|
458
|
-
|
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
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
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
|
-
|
581
|
-
|
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
|
-
|
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
|
-
|
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
|
12
|
-
VALUE
|
11
|
+
void rbduckdb_init_duckdb_result(void);
|
12
|
+
VALUE rbduckdb_create_result(void);
|
13
13
|
|
14
14
|
#endif
|
15
15
|
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
data/ext/duckdb/util.c
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#include "ruby-duckdb.h"
|
2
2
|
|
3
|
-
duckdb_date
|
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
|
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
|
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
|
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
|
5
|
-
duckdb_time
|
6
|
-
duckdb_timestamp
|
7
|
-
void
|
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
|
data/lib/duckdb/appender.rb
CHANGED
@@ -86,16 +86,7 @@ module DuckDB
|
|
86
86
|
# appender.flush
|
87
87
|
#
|
88
88
|
def append_time(value)
|
89
|
-
time =
|
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
|