duckdb 0.9.1.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/CHANGELOG.md +4 -0
- data/Gemfile.lock +2 -2
- 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/pending_result.c +25 -2
- data/ext/duckdb/pending_result.h +1 -1
- data/ext/duckdb/prepared_statement.c +6 -6
- data/ext/duckdb/prepared_statement.h +1 -1
- data/ext/duckdb/result.c +3 -3
- data/ext/duckdb/result.h +2 -2
- 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/prepared_statement.rb +36 -40
- data/lib/duckdb/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b492788be53be66a956ad49e4cd8a82ffa6273c12f037b2c0abd51253321802f
|
4
|
+
data.tar.gz: 50571029b1d1160a7abb6ac223bd4cda4f3791b29d26cdebac6b795f160a2a14
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d80355e181599217574191f3acba24d6dbcb37e4a73b774689590f42fc9b92032d4a4285962ee65100d3a3186825b29f09066d9fd0f8f24ce46aaec85cba4701
|
7
|
+
data.tar.gz: b126f7e0057c77cae338f7c6b76d4b775c52b06f84936ebd6208a3357148ababa8c8c3aaca727dacf4b7ed05b5f5da2bedc74d8b1d46f170ddc418d4c9e125fa
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
duckdb (0.9.1.
|
4
|
+
duckdb (0.9.1.2)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -14,7 +14,7 @@ GEM
|
|
14
14
|
racc (~> 1.4)
|
15
15
|
nokogiri (1.15.4-x86_64-linux)
|
16
16
|
racc (~> 1.4)
|
17
|
-
racc (1.7.
|
17
|
+
racc (1.7.3)
|
18
18
|
rake (13.1.0)
|
19
19
|
rake-compiler (1.2.5)
|
20
20
|
rake
|
data/ext/duckdb/appender.c
CHANGED
@@ -285,7 +285,7 @@ static VALUE appender__append_date(VALUE self, VALUE year, VALUE month, VALUE da
|
|
285
285
|
rubyDuckDBAppender *ctx;
|
286
286
|
|
287
287
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
288
|
-
dt =
|
288
|
+
dt = rbduckdb_to_duckdb_date_from_value(year, month, day);
|
289
289
|
|
290
290
|
if (duckdb_append_date(ctx->appender, dt) == DuckDBError) {
|
291
291
|
rb_raise(eDuckDBError, "failed to append date");
|
@@ -298,7 +298,7 @@ static VALUE appender__append_interval(VALUE self, VALUE months, VALUE days, VAL
|
|
298
298
|
rubyDuckDBAppender *ctx;
|
299
299
|
|
300
300
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
301
|
-
|
301
|
+
rbduckdb_to_duckdb_interval_from_value(&interval, months, days, micros);
|
302
302
|
|
303
303
|
if (duckdb_append_interval(ctx->appender, interval) == DuckDBError) {
|
304
304
|
rb_raise(eDuckDBError, "failed to append interval");
|
@@ -311,7 +311,7 @@ static VALUE appender__append_time(VALUE self, VALUE hour, VALUE min, VALUE sec,
|
|
311
311
|
rubyDuckDBAppender *ctx;
|
312
312
|
|
313
313
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
314
|
-
time =
|
314
|
+
time = rbduckdb_to_duckdb_time_from_value(hour, min, sec, micros);
|
315
315
|
|
316
316
|
if (duckdb_append_time(ctx->appender, time) == DuckDBError) {
|
317
317
|
rb_raise(eDuckDBError, "failed to append time");
|
@@ -326,7 +326,7 @@ static VALUE appender__append_timestamp(VALUE self, VALUE year, VALUE month, VAL
|
|
326
326
|
|
327
327
|
TypedData_Get_Struct(self, rubyDuckDBAppender, &appender_data_type, ctx);
|
328
328
|
|
329
|
-
timestamp =
|
329
|
+
timestamp = rbduckdb_to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
|
330
330
|
|
331
331
|
if (duckdb_append_timestamp(ctx->appender, timestamp) == DuckDBError) {
|
332
332
|
rb_raise(eDuckDBError, "failed to append timestamp");
|
@@ -369,7 +369,7 @@ static VALUE appender_close(VALUE self) {
|
|
369
369
|
return self;
|
370
370
|
}
|
371
371
|
|
372
|
-
void
|
372
|
+
void rbduckdb_init_duckdb_appender(void) {
|
373
373
|
cDuckDBAppender = rb_define_class_under(mDuckDB, "Appender", rb_cObject);
|
374
374
|
rb_define_alloc_func(cDuckDBAppender, allocate);
|
375
375
|
rb_define_method(cDuckDBAppender, "initialize", appender_initialize, 3);
|
data/ext/duckdb/appender.h
CHANGED
data/ext/duckdb/blob.c
CHANGED
data/ext/duckdb/blob.h
CHANGED
data/ext/duckdb/column.c
CHANGED
@@ -68,7 +68,7 @@ VALUE duckdb_column_get_name(VALUE oDuckDBColumn) {
|
|
68
68
|
return rb_utf8_str_new_cstr(duckdb_column_name(&(ctxresult->result), ctx->col));
|
69
69
|
}
|
70
70
|
|
71
|
-
VALUE
|
71
|
+
VALUE rbduckdb_create_column(VALUE oDuckDBResult, idx_t col) {
|
72
72
|
VALUE obj;
|
73
73
|
rubyDuckDBColumn *ctx;
|
74
74
|
|
@@ -81,7 +81,7 @@ VALUE create_column(VALUE oDuckDBResult, idx_t col) {
|
|
81
81
|
return obj;
|
82
82
|
}
|
83
83
|
|
84
|
-
void
|
84
|
+
void rbduckdb_init_duckdb_column(void) {
|
85
85
|
cDuckDBColumn = rb_define_class_under(mDuckDB, "Column", rb_cObject);
|
86
86
|
rb_define_alloc_func(cDuckDBColumn, allocate);
|
87
87
|
|
data/ext/duckdb/column.h
CHANGED
@@ -8,7 +8,7 @@ struct _rubyDuckDBColumn {
|
|
8
8
|
|
9
9
|
typedef struct _rubyDuckDBColumn rubyDuckDBColumn;
|
10
10
|
|
11
|
-
void
|
12
|
-
VALUE
|
11
|
+
void rbduckdb_init_duckdb_column(void);
|
12
|
+
VALUE rbduckdb_create_column(VALUE oDuckDBResult, idx_t col);
|
13
13
|
|
14
14
|
#endif
|
data/ext/duckdb/config.c
CHANGED
@@ -79,7 +79,7 @@ static VALUE config_set_config(VALUE self, VALUE key, VALUE value) {
|
|
79
79
|
return self;
|
80
80
|
}
|
81
81
|
|
82
|
-
void
|
82
|
+
void rbduckdb_init_duckdb_config(void) {
|
83
83
|
cDuckDBConfig = rb_define_class_under(mDuckDB, "Config", rb_cObject);
|
84
84
|
rb_define_alloc_func(cDuckDBConfig, allocate);
|
85
85
|
rb_define_singleton_method(cDuckDBConfig, "size", config_s_size, 0);
|
data/ext/duckdb/config.h
CHANGED
data/ext/duckdb/connection.c
CHANGED
@@ -6,6 +6,12 @@ static void deallocate(void *ctx);
|
|
6
6
|
static VALUE allocate(VALUE klass);
|
7
7
|
static size_t memsize(const void *p);
|
8
8
|
static VALUE duckdb_connection_disconnect(VALUE self);
|
9
|
+
|
10
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
11
|
+
static VALUE duckdb_connection_interrupt(VALUE self);
|
12
|
+
static VALUE duckdb_connection_query_progress(VALUE self);
|
13
|
+
#endif
|
14
|
+
|
9
15
|
static VALUE duckdb_connection_connect(VALUE self, VALUE oDuckDBDatabase);
|
10
16
|
static VALUE duckdb_connection_query_sql(VALUE self, VALUE str);
|
11
17
|
|
@@ -37,12 +43,12 @@ rubyDuckDBConnection *get_struct_connection(VALUE obj) {
|
|
37
43
|
return ctx;
|
38
44
|
}
|
39
45
|
|
40
|
-
VALUE
|
46
|
+
VALUE rbduckdb_create_connection(VALUE oDuckDBDatabase) {
|
41
47
|
rubyDuckDB *ctxdb;
|
42
48
|
rubyDuckDBConnection *ctxcon;
|
43
49
|
VALUE obj;
|
44
50
|
|
45
|
-
ctxdb =
|
51
|
+
ctxdb = rbduckdb_get_struct_database(oDuckDBDatabase);
|
46
52
|
|
47
53
|
obj = allocate(cDuckDBConnection);
|
48
54
|
TypedData_Get_Struct(obj, rubyDuckDBConnection, &connection_data_type, ctxcon);
|
@@ -51,7 +57,6 @@ VALUE create_connection(VALUE oDuckDBDatabase) {
|
|
51
57
|
rb_raise(eDuckDBError, "connection error");
|
52
58
|
}
|
53
59
|
|
54
|
-
// rb_ivar_set(obj, rb_intern("database"), oDuckDBDatabase);
|
55
60
|
return obj;
|
56
61
|
}
|
57
62
|
|
@@ -64,6 +69,57 @@ static VALUE duckdb_connection_disconnect(VALUE self) {
|
|
64
69
|
return self;
|
65
70
|
}
|
66
71
|
|
72
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
73
|
+
/*
|
74
|
+
* call-seq:
|
75
|
+
* connection.interrupt -> nil
|
76
|
+
*
|
77
|
+
* Interrupts the currently running query.
|
78
|
+
*
|
79
|
+
* db = DuckDB::Database.open
|
80
|
+
* conn = db.connect
|
81
|
+
* con.query('SET ENABLE_PROGRESS_BAR=true')
|
82
|
+
* con.query('SET ENABLE_PROGRESS_BAR_PRINT=false')
|
83
|
+
* pending_result = con.async_query('slow query')
|
84
|
+
*
|
85
|
+
* pending_result.execute_task
|
86
|
+
* con.interrupt # => nil
|
87
|
+
*/
|
88
|
+
static VALUE duckdb_connection_interrupt(VALUE self) {
|
89
|
+
rubyDuckDBConnection *ctx;
|
90
|
+
|
91
|
+
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
92
|
+
duckdb_interrupt(ctx->con);
|
93
|
+
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
/*
|
98
|
+
* Returns the progress of the currently running query.
|
99
|
+
*
|
100
|
+
* require 'duckdb'
|
101
|
+
*
|
102
|
+
* db = DuckDB::Database.open
|
103
|
+
* conn = db.connect
|
104
|
+
* con.query('SET ENABLE_PROGRESS_BAR=true')
|
105
|
+
* con.query('SET ENABLE_PROGRESS_BAR_PRINT=false')
|
106
|
+
* con.query_progress # => -1.0
|
107
|
+
* pending_result = con.async_query('slow query')
|
108
|
+
* con.query_progress # => 0.0
|
109
|
+
* pending_result.execute_task
|
110
|
+
* con.query_progress # => Float
|
111
|
+
*/
|
112
|
+
static VALUE duckdb_connection_query_progress(VALUE self) {
|
113
|
+
rubyDuckDBConnection *ctx;
|
114
|
+
double progress;
|
115
|
+
|
116
|
+
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
117
|
+
progress = duckdb_query_progress(ctx->con);
|
118
|
+
|
119
|
+
return DBL2NUM(progress);
|
120
|
+
}
|
121
|
+
#endif
|
122
|
+
|
67
123
|
static VALUE duckdb_connection_connect(VALUE self, VALUE oDuckDBDatabase) {
|
68
124
|
rubyDuckDBConnection *ctx;
|
69
125
|
rubyDuckDB *ctxdb;
|
@@ -71,7 +127,7 @@ static VALUE duckdb_connection_connect(VALUE self, VALUE oDuckDBDatabase) {
|
|
71
127
|
if (!rb_obj_is_kind_of(oDuckDBDatabase, cDuckDBDatabase)) {
|
72
128
|
rb_raise(rb_eTypeError, "The first argument must be DuckDB::Database object.");
|
73
129
|
}
|
74
|
-
ctxdb =
|
130
|
+
ctxdb = rbduckdb_get_struct_database(oDuckDBDatabase);
|
75
131
|
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
76
132
|
|
77
133
|
if (duckdb_connect(ctxdb->db, &(ctx->con)) == DuckDBError) {
|
@@ -85,7 +141,7 @@ static VALUE duckdb_connection_query_sql(VALUE self, VALUE str) {
|
|
85
141
|
rubyDuckDBConnection *ctx;
|
86
142
|
rubyDuckDBResult *ctxr;
|
87
143
|
|
88
|
-
VALUE result =
|
144
|
+
VALUE result = rbduckdb_create_result();
|
89
145
|
|
90
146
|
TypedData_Get_Struct(self, rubyDuckDBConnection, &connection_data_type, ctx);
|
91
147
|
ctxr = get_struct_result(result);
|
@@ -100,11 +156,15 @@ static VALUE duckdb_connection_query_sql(VALUE self, VALUE str) {
|
|
100
156
|
return result;
|
101
157
|
}
|
102
158
|
|
103
|
-
void
|
159
|
+
void rbduckdb_init_duckdb_connection(void) {
|
104
160
|
cDuckDBConnection = rb_define_class_under(mDuckDB, "Connection", rb_cObject);
|
105
161
|
rb_define_alloc_func(cDuckDBConnection, allocate);
|
106
162
|
|
107
163
|
rb_define_method(cDuckDBConnection, "disconnect", duckdb_connection_disconnect, 0);
|
164
|
+
#ifdef HAVE_DUCKDB_H_GE_V090
|
165
|
+
rb_define_method(cDuckDBConnection, "interrupt", duckdb_connection_interrupt, 0);
|
166
|
+
rb_define_method(cDuckDBConnection, "query_progress", duckdb_connection_query_progress, 0);
|
167
|
+
#endif
|
108
168
|
rb_define_private_method(cDuckDBConnection, "_connect", duckdb_connection_connect, 1);
|
109
169
|
rb_define_private_method(cDuckDBConnection, "query_sql", duckdb_connection_query_sql, 1);
|
110
170
|
}
|
data/ext/duckdb/connection.h
CHANGED
@@ -8,7 +8,7 @@ struct _rubyDuckDBConnection {
|
|
8
8
|
typedef struct _rubyDuckDBConnection rubyDuckDBConnection;
|
9
9
|
|
10
10
|
rubyDuckDBConnection *get_struct_connection(VALUE obj);
|
11
|
-
void
|
12
|
-
VALUE
|
11
|
+
void rbduckdb_init_duckdb_connection(void);
|
12
|
+
VALUE rbduckdb_create_connection(VALUE oDuckDBDatabase);
|
13
13
|
|
14
14
|
#endif
|
data/ext/duckdb/converter.h
CHANGED
data/ext/duckdb/conveter.c
CHANGED
data/ext/duckdb/database.c
CHANGED
@@ -37,7 +37,7 @@ static VALUE allocate(VALUE klass) {
|
|
37
37
|
return TypedData_Wrap_Struct(klass, &database_data_type, ctx);
|
38
38
|
}
|
39
39
|
|
40
|
-
rubyDuckDB *
|
40
|
+
rubyDuckDB *rbduckdb_get_struct_database(VALUE obj) {
|
41
41
|
rubyDuckDB *ctx;
|
42
42
|
TypedData_Get_Struct(obj, rubyDuckDB, &database_data_type, ctx);
|
43
43
|
return ctx;
|
@@ -99,7 +99,7 @@ static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBData
|
|
99
99
|
}
|
100
100
|
|
101
101
|
static VALUE duckdb_database_connect(VALUE self) {
|
102
|
-
return
|
102
|
+
return rbduckdb_create_connection(self);
|
103
103
|
}
|
104
104
|
|
105
105
|
/*
|
@@ -115,7 +115,7 @@ static VALUE duckdb_database_close(VALUE self) {
|
|
115
115
|
return self;
|
116
116
|
}
|
117
117
|
|
118
|
-
void
|
118
|
+
void rbduckdb_init_duckdb_database(void) {
|
119
119
|
cDuckDBDatabase = rb_define_class_under(mDuckDB, "Database", rb_cObject);
|
120
120
|
rb_define_alloc_func(cDuckDBDatabase, allocate);
|
121
121
|
rb_define_singleton_method(cDuckDBDatabase, "_open", duckdb_database_s_open, -1);
|
data/ext/duckdb/database.h
CHANGED
data/ext/duckdb/duckdb.c
CHANGED
@@ -22,15 +22,15 @@ Init_duckdb_native(void) {
|
|
22
22
|
|
23
23
|
rb_define_singleton_method(mDuckDB, "library_version", duckdb_s_library_version, 0);
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
rbduckdb_init_duckdb_error();
|
26
|
+
rbduckdb_init_duckdb_database();
|
27
|
+
rbduckdb_init_duckdb_connection();
|
28
|
+
rbduckdb_init_duckdb_result();
|
29
|
+
rbduckdb_init_duckdb_column();
|
30
|
+
rbduckdb_init_duckdb_prepared_statement();
|
31
|
+
rbduckdb_init_duckdb_pending_result();
|
32
|
+
rbduckdb_init_duckdb_blob();
|
33
|
+
rbduckdb_init_duckdb_appender();
|
34
|
+
rbduckdb_init_duckdb_config();
|
35
|
+
rbduckdb_init_duckdb_converter();
|
36
36
|
}
|
data/ext/duckdb/error.c
CHANGED
data/ext/duckdb/error.h
CHANGED
data/ext/duckdb/pending_result.c
CHANGED
@@ -48,6 +48,17 @@ static VALUE duckdb_pending_result_initialize(VALUE self, VALUE oDuckDBPreparedS
|
|
48
48
|
return self;
|
49
49
|
}
|
50
50
|
|
51
|
+
/*
|
52
|
+
* call-seq:
|
53
|
+
* pending_result.execute_task -> nil
|
54
|
+
*
|
55
|
+
* Executes the task in the pending result.
|
56
|
+
*
|
57
|
+
* db = DuckDB::Database.open
|
58
|
+
* conn = db.connect
|
59
|
+
* pending_result = conn.async_query("slow query")
|
60
|
+
* pending_result.execute_task
|
61
|
+
*/
|
51
62
|
static VALUE duckdb_pending_result_execute_task(VALUE self) {
|
52
63
|
rubyDuckDBPendingResult *ctx = get_struct_pending_result(self);
|
53
64
|
ctx->state = duckdb_pending_execute_task(ctx->pending_result);
|
@@ -61,10 +72,22 @@ static VALUE duckdb_pending_result_execution_finished_p(VALUE self) {
|
|
61
72
|
}
|
62
73
|
#endif
|
63
74
|
|
75
|
+
/*
|
76
|
+
* call-seq:
|
77
|
+
* pending_result.execute_pending -> DuckDB::Result
|
78
|
+
*
|
79
|
+
* Get DuckDB::Result object after query execution finished.
|
80
|
+
*
|
81
|
+
* db = DuckDB::Database.open
|
82
|
+
* conn = db.connect
|
83
|
+
* pending_result = conn.async_query("slow query")
|
84
|
+
* pending_result.execute_task while pending_result.state != :ready
|
85
|
+
* result = pending_result.execute_pending # => DuckDB::Result
|
86
|
+
*/
|
64
87
|
static VALUE duckdb_pending_result_execute_pending(VALUE self) {
|
65
88
|
rubyDuckDBPendingResult *ctx;
|
66
89
|
rubyDuckDBResult *ctxr;
|
67
|
-
VALUE result =
|
90
|
+
VALUE result = rbduckdb_create_result();
|
68
91
|
|
69
92
|
TypedData_Get_Struct(self, rubyDuckDBPendingResult, &pending_result_data_type, ctx);
|
70
93
|
ctxr = get_struct_result(result);
|
@@ -85,7 +108,7 @@ rubyDuckDBPendingResult *get_struct_pending_result(VALUE obj) {
|
|
85
108
|
return ctx;
|
86
109
|
}
|
87
110
|
|
88
|
-
void
|
111
|
+
void rbduckdb_init_duckdb_pending_result(void) {
|
89
112
|
cDuckDBPendingResult = rb_define_class_under(mDuckDB, "PendingResult", rb_cObject);
|
90
113
|
rb_define_alloc_func(cDuckDBPendingResult, allocate);
|
91
114
|
|
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
|
@@ -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
@@ -229,7 +229,7 @@ static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
|
|
229
229
|
|
230
230
|
VALUE ary = rb_ary_new2(column_count);
|
231
231
|
for(col_idx = 0; col_idx < column_count; col_idx++) {
|
232
|
-
VALUE column =
|
232
|
+
VALUE column = rbduckdb_create_column(oDuckDBResult, col_idx);
|
233
233
|
rb_ary_store(ary, col_idx, column);
|
234
234
|
}
|
235
235
|
return ary;
|
@@ -397,7 +397,7 @@ static VALUE duckdb_result__enum_dictionary_value(VALUE oDuckDBResult, VALUE col
|
|
397
397
|
return value;
|
398
398
|
}
|
399
399
|
|
400
|
-
VALUE
|
400
|
+
VALUE rbduckdb_create_result(void) {
|
401
401
|
return allocate(cDuckDBResult);
|
402
402
|
}
|
403
403
|
|
@@ -717,7 +717,7 @@ static VALUE duckdb_result_chunk_each(VALUE oDuckDBResult) {
|
|
717
717
|
return Qnil;
|
718
718
|
}
|
719
719
|
|
720
|
-
void
|
720
|
+
void rbduckdb_init_duckdb_result(void) {
|
721
721
|
cDuckDBResult = rb_define_class_under(mDuckDB, "Result", rb_cObject);
|
722
722
|
rb_define_alloc_func(cDuckDBResult, allocate);
|
723
723
|
|
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/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
|
@@ -24,21 +24,43 @@ module DuckDB
|
|
24
24
|
PendingResult.new(self)
|
25
25
|
end
|
26
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
|
+
|
27
48
|
# binds i-th parameter with SQL prepared statement.
|
28
49
|
# The first argument is index of parameter.
|
29
50
|
# The index of first parameter is 1 not 0.
|
30
51
|
# The second argument value is to expected Integer value.
|
31
52
|
# This method uses bind_varchar internally.
|
53
|
+
#
|
32
54
|
# require 'duckdb'
|
33
55
|
# db = DuckDB::Database.open('duckdb_database')
|
34
56
|
# con = db.connect
|
35
57
|
# sql ='SELECT name FROM users WHERE bigint_col = ?'
|
36
58
|
# stmt = PreparedStatement.new(con, sql)
|
37
59
|
# stmt.bind_hugeint(1, 1_234_567_890_123_456_789_012_345)
|
38
|
-
def bind_hugeint(
|
60
|
+
def bind_hugeint(index, value)
|
39
61
|
case value
|
40
62
|
when Integer
|
41
|
-
bind_varchar(
|
63
|
+
bind_varchar(index, value.to_s)
|
42
64
|
else
|
43
65
|
raise(ArgumentError, "2nd argument `#{value}` must be Integer.")
|
44
66
|
end
|
@@ -49,6 +71,7 @@ module DuckDB
|
|
49
71
|
# The index of first parameter is 1 not 0.
|
50
72
|
# The second argument value must be Integer value.
|
51
73
|
# This method uses duckdb_bind_hugeint internally.
|
74
|
+
#
|
52
75
|
# require 'duckdb'
|
53
76
|
# db = DuckDB::Database.open('duckdb_database')
|
54
77
|
# con = db.connect
|
@@ -73,19 +96,10 @@ module DuckDB
|
|
73
96
|
# stmt.bind(1, Date.today)
|
74
97
|
# # or you can specify date string.
|
75
98
|
# # stmt.bind(1, '2021-02-23')
|
76
|
-
def bind_date(
|
77
|
-
|
78
|
-
when Date, Time
|
79
|
-
date = value
|
80
|
-
else
|
81
|
-
begin
|
82
|
-
date = Date.parse(value)
|
83
|
-
rescue => e
|
84
|
-
raise(ArgumentError, "Cannot parse argument value to date. #{e.message}")
|
85
|
-
end
|
86
|
-
end
|
99
|
+
def bind_date(index, value)
|
100
|
+
date = _parse_date(value)
|
87
101
|
|
88
|
-
_bind_date(
|
102
|
+
_bind_date(index, date.year, date.month, date.day)
|
89
103
|
end
|
90
104
|
|
91
105
|
# binds i-th parameter with SQL prepared statement.
|
@@ -101,19 +115,10 @@ module DuckDB
|
|
101
115
|
# stmt.bind(1, Time.now)
|
102
116
|
# # or you can specify time string.
|
103
117
|
# # stmt.bind(1, '07:39:45')
|
104
|
-
def bind_time(
|
105
|
-
|
106
|
-
when Time
|
107
|
-
time = value
|
108
|
-
else
|
109
|
-
begin
|
110
|
-
time = Time.parse(value)
|
111
|
-
rescue => e
|
112
|
-
raise(ArgumentError, "Cannot parse argument value to time. #{e.message}")
|
113
|
-
end
|
114
|
-
end
|
118
|
+
def bind_time(index, value)
|
119
|
+
time = _parse_time(value)
|
115
120
|
|
116
|
-
_bind_time(
|
121
|
+
_bind_time(index, time.hour, time.min, time.sec, time.usec)
|
117
122
|
end
|
118
123
|
|
119
124
|
# binds i-th parameter with SQL prepared statement.
|
@@ -129,19 +134,10 @@ module DuckDB
|
|
129
134
|
# stmt.bind(1, Time.now)
|
130
135
|
# # or you can specify timestamp string.
|
131
136
|
# # stmt.bind(1, '2022-02-23 07:39:45')
|
132
|
-
def bind_timestamp(
|
133
|
-
|
134
|
-
when Time
|
135
|
-
time = value
|
136
|
-
else
|
137
|
-
begin
|
138
|
-
time = Time.parse(value)
|
139
|
-
rescue => e
|
140
|
-
raise(ArgumentError, "Cannot parse argument value to time. #{e.message}")
|
141
|
-
end
|
142
|
-
end
|
137
|
+
def bind_timestamp(index, value)
|
138
|
+
time = _parse_time(value)
|
143
139
|
|
144
|
-
_bind_timestamp(
|
140
|
+
_bind_timestamp(index, time.year, time.month, time.day, time.hour, time.min, time.sec, time.usec)
|
145
141
|
end
|
146
142
|
|
147
143
|
# binds i-th parameter with SQL prepared statement.
|
@@ -155,9 +151,9 @@ module DuckDB
|
|
155
151
|
# sql ='SELECT value FROM intervals WHERE interval = ?'
|
156
152
|
# stmt = PreparedStatement.new(con, sql)
|
157
153
|
# stmt.bind(1, 'P1Y2D')
|
158
|
-
def bind_interval(
|
154
|
+
def bind_interval(index, value)
|
159
155
|
value = Interval.to_interval(value)
|
160
|
-
_bind_interval(
|
156
|
+
_bind_interval(index, value.interval_months, value.interval_days, value.interval_micros)
|
161
157
|
end
|
162
158
|
|
163
159
|
# binds i-th parameter with SQL prepared statement.
|
data/lib/duckdb/version.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
|