duckdb 0.9.1.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/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
|