duckdb 0.9.1 → 0.9.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test_on_macos.yml +1 -1
- data/.github/workflows/test_on_ubuntu.yml +1 -1
- data/.github/workflows/test_on_windows.yml +1 -1
- data/CHANGELOG.md +21 -6
- data/Gemfile.lock +4 -4
- 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 -10
- data/ext/duckdb/error.c +1 -1
- data/ext/duckdb/error.h +1 -1
- data/ext/duckdb/extconf.rb +1 -6
- data/ext/duckdb/pending_result.c +123 -0
- data/ext/duckdb/pending_result.h +13 -0
- data/ext/duckdb/prepared_statement.c +12 -7
- data/ext/duckdb/prepared_statement.h +2 -1
- data/ext/duckdb/result.c +3 -9
- data/ext/duckdb/result.h +2 -2
- data/ext/duckdb/ruby-duckdb.h +1 -8
- 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 +28 -8
- data/lib/duckdb/converter.rb +27 -1
- data/lib/duckdb/library_version.rb +1 -1
- data/lib/duckdb/pending_result.rb +39 -0
- data/lib/duckdb/prepared_statement.rb +40 -40
- data/lib/duckdb/result.rb +16 -12
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +1 -0
- metadata +5 -2
@@ -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);
|
@@ -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
|
-
|
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
|
-
|
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 =
|
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
|
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
|
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
|
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
@@ -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
|
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
|
data/lib/duckdb/connection.rb
CHANGED
@@ -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, **
|
29
|
-
return query_sql(sql) if args.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
|
-
|
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
|
data/lib/duckdb/converter.rb
CHANGED
@@ -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
|
@@ -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(
|
60
|
+
def bind_hugeint(index, value)
|
35
61
|
case value
|
36
62
|
when Integer
|
37
|
-
bind_varchar(
|
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(
|
73
|
-
|
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(
|
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(
|
101
|
-
|
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(
|
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(
|
129
|
-
|
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(
|
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(
|
154
|
+
def bind_interval(index, value)
|
155
155
|
value = Interval.to_interval(value)
|
156
|
-
_bind_interval(
|
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
|
-
|
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
|
-
|
46
|
-
|
43
|
+
class << self
|
44
|
+
def new
|
45
|
+
raise DuckDB::Error, 'DuckDB::Result cannot be instantiated directly.'
|
46
|
+
end
|
47
47
|
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
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(
|
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)
|
data/lib/duckdb/version.rb
CHANGED
data/lib/duckdb.rb
CHANGED
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-
|
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
|