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