duckdb 0.3.1.0 → 0.3.4.0
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 +31 -9
- data/.github/workflows/test_on_ubuntu.yml +11 -3
- data/.github/workflows/test_on_windows.yml +16 -7
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +4 -3
- data/README.md +32 -3
- data/ext/duckdb/appender.c +7 -59
- data/ext/duckdb/appender.h +0 -5
- data/ext/duckdb/blob.c +1 -5
- data/ext/duckdb/blob.h +0 -4
- data/ext/duckdb/column.c +73 -0
- data/ext/duckdb/column.h +14 -0
- data/ext/duckdb/config.c +2 -4
- data/ext/duckdb/connection.c +2 -3
- data/ext/duckdb/duckdb.c +2 -11
- data/ext/duckdb/error.c +1 -2
- data/ext/duckdb/extconf.rb +17 -21
- data/ext/duckdb/prepared_statement.c +100 -46
- data/ext/duckdb/result.c +51 -20
- data/ext/duckdb/ruby-duckdb.h +7 -20
- data/ext/duckdb/util.c +45 -0
- data/ext/duckdb/util.h +13 -0
- data/lib/duckdb/appender.rb +207 -261
- data/lib/duckdb/column.rb +55 -0
- data/lib/duckdb/config.rb +1 -4
- data/lib/duckdb/converter.rb +52 -0
- data/lib/duckdb/prepared_statement.rb +111 -8
- data/lib/duckdb/version.rb +1 -1
- data/lib/duckdb.rb +2 -0
- metadata +9 -3
@@ -2,22 +2,40 @@
|
|
2
2
|
|
3
3
|
static VALUE cDuckDBPreparedStatement;
|
4
4
|
|
5
|
-
static void deallocate(void *ctx)
|
6
|
-
|
5
|
+
static void deallocate(void *ctx);
|
6
|
+
static VALUE allocate(VALUE klass);
|
7
|
+
static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query);
|
8
|
+
static VALUE duckdb_prepared_statement_nparams(VALUE self);
|
9
|
+
static VALUE duckdb_prepared_statement_execute(VALUE self);
|
10
|
+
static idx_t check_index(VALUE vidx);
|
11
|
+
static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val);
|
12
|
+
static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val);
|
13
|
+
static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val);
|
14
|
+
static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE val);
|
15
|
+
static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE val);
|
16
|
+
static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE val);
|
17
|
+
static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE val);
|
18
|
+
static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str);
|
19
|
+
static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob);
|
20
|
+
static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx);
|
21
|
+
static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day);
|
22
|
+
static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
23
|
+
static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
24
|
+
static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros);
|
25
|
+
|
26
|
+
static void deallocate(void *ctx) {
|
7
27
|
rubyDuckDBPreparedStatement *p = (rubyDuckDBPreparedStatement *)ctx;
|
8
28
|
|
9
29
|
duckdb_destroy_prepare(&(p->prepared_statement));
|
10
30
|
xfree(p);
|
11
31
|
}
|
12
32
|
|
13
|
-
static VALUE allocate(VALUE klass)
|
14
|
-
{
|
33
|
+
static VALUE allocate(VALUE klass) {
|
15
34
|
rubyDuckDBPreparedStatement *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBPreparedStatement));
|
16
35
|
return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
|
17
36
|
}
|
18
37
|
|
19
|
-
static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query)
|
20
|
-
{
|
38
|
+
static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query) {
|
21
39
|
rubyDuckDBConnection *ctxcon;
|
22
40
|
rubyDuckDBPreparedStatement *ctx;
|
23
41
|
|
@@ -40,23 +58,14 @@ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE q
|
|
40
58
|
return self;
|
41
59
|
}
|
42
60
|
|
43
|
-
static VALUE duckdb_prepared_statement_nparams(VALUE self)
|
44
|
-
{
|
61
|
+
static VALUE duckdb_prepared_statement_nparams(VALUE self) {
|
45
62
|
rubyDuckDBPreparedStatement *ctx;
|
46
63
|
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
47
|
-
#ifdef HAVE_DUCKDB_NPARAMS_029
|
48
64
|
return rb_int2big(duckdb_nparams(ctx->prepared_statement));
|
49
|
-
#else
|
50
|
-
if (duckdb_nparams(ctx->prepared_statement, &(ctx->nparams)) == DuckDBError) {
|
51
|
-
rb_raise(eDuckDBError, "failed to get number of parameters");
|
52
|
-
}
|
53
|
-
return rb_int2big(ctx->nparams);
|
54
|
-
#endif
|
55
65
|
}
|
56
66
|
|
57
67
|
|
58
|
-
static VALUE duckdb_prepared_statement_execute(VALUE self)
|
59
|
-
{
|
68
|
+
static VALUE duckdb_prepared_statement_execute(VALUE self) {
|
60
69
|
rubyDuckDBPreparedStatement *ctx;
|
61
70
|
rubyDuckDBResult *ctxr;
|
62
71
|
VALUE result = create_result();
|
@@ -64,13 +73,12 @@ static VALUE duckdb_prepared_statement_execute(VALUE self)
|
|
64
73
|
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
65
74
|
Data_Get_Struct(result, rubyDuckDBResult, ctxr);
|
66
75
|
if (duckdb_execute_prepared(ctx->prepared_statement, &(ctxr->result)) == DuckDBError) {
|
67
|
-
rb_raise(eDuckDBError, "%s", ctxr->result
|
76
|
+
rb_raise(eDuckDBError, "%s", duckdb_result_error(&(ctxr->result)));
|
68
77
|
}
|
69
78
|
return result;
|
70
79
|
}
|
71
80
|
|
72
|
-
static idx_t check_index(VALUE vidx)
|
73
|
-
{
|
81
|
+
static idx_t check_index(VALUE vidx) {
|
74
82
|
idx_t idx = FIX2INT(vidx);
|
75
83
|
if (idx <= 0) {
|
76
84
|
rb_raise(rb_eArgError, "index of parameter must be greater than 0");
|
@@ -78,8 +86,7 @@ static idx_t check_index(VALUE vidx)
|
|
78
86
|
return idx;
|
79
87
|
}
|
80
88
|
|
81
|
-
static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val)
|
82
|
-
{
|
89
|
+
static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val) {
|
83
90
|
rubyDuckDBPreparedStatement *ctx;
|
84
91
|
idx_t idx = check_index(vidx);
|
85
92
|
|
@@ -94,8 +101,7 @@ static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE v
|
|
94
101
|
return self;
|
95
102
|
}
|
96
103
|
|
97
|
-
static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val)
|
98
|
-
{
|
104
|
+
static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val) {
|
99
105
|
rubyDuckDBPreparedStatement *ctx;
|
100
106
|
idx_t idx = check_index(vidx);
|
101
107
|
int8_t i8val = (int8_t)NUM2INT(val);
|
@@ -108,8 +114,7 @@ static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE v
|
|
108
114
|
return self;
|
109
115
|
}
|
110
116
|
|
111
|
-
static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val)
|
112
|
-
{
|
117
|
+
static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val) {
|
113
118
|
rubyDuckDBPreparedStatement *ctx;
|
114
119
|
idx_t idx = check_index(vidx);
|
115
120
|
int16_t i16val = NUM2INT(val);
|
@@ -122,8 +127,7 @@ static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE
|
|
122
127
|
return self;
|
123
128
|
}
|
124
129
|
|
125
|
-
static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE val)
|
126
|
-
{
|
130
|
+
static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE val) {
|
127
131
|
rubyDuckDBPreparedStatement *ctx;
|
128
132
|
idx_t idx = check_index(vidx);
|
129
133
|
int32_t i32val = NUM2INT(val);
|
@@ -136,8 +140,7 @@ static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE
|
|
136
140
|
return self;
|
137
141
|
}
|
138
142
|
|
139
|
-
static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE val)
|
140
|
-
{
|
143
|
+
static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE val) {
|
141
144
|
rubyDuckDBPreparedStatement *ctx;
|
142
145
|
idx_t idx = check_index(vidx);
|
143
146
|
int64_t i64val = NUM2LL(val);
|
@@ -150,8 +153,7 @@ static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE
|
|
150
153
|
return self;
|
151
154
|
}
|
152
155
|
|
153
|
-
static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE val)
|
154
|
-
{
|
156
|
+
static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE val) {
|
155
157
|
rubyDuckDBPreparedStatement *ctx;
|
156
158
|
idx_t idx = check_index(vidx);
|
157
159
|
double dbl = NUM2DBL(val);
|
@@ -164,8 +166,7 @@ static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE
|
|
164
166
|
return self;
|
165
167
|
}
|
166
168
|
|
167
|
-
static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE val)
|
168
|
-
{
|
169
|
+
static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE val) {
|
169
170
|
rubyDuckDBPreparedStatement *ctx;
|
170
171
|
idx_t idx = check_index(vidx);
|
171
172
|
double dbl = NUM2DBL(val);
|
@@ -178,8 +179,7 @@ static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE
|
|
178
179
|
return self;
|
179
180
|
}
|
180
181
|
|
181
|
-
static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str)
|
182
|
-
{
|
182
|
+
static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str) {
|
183
183
|
rubyDuckDBPreparedStatement *ctx;
|
184
184
|
idx_t idx = check_index(vidx);
|
185
185
|
|
@@ -190,9 +190,7 @@ static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALU
|
|
190
190
|
return self;
|
191
191
|
}
|
192
192
|
|
193
|
-
|
194
|
-
static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob)
|
195
|
-
{
|
193
|
+
static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob) {
|
196
194
|
rubyDuckDBPreparedStatement *ctx;
|
197
195
|
idx_t idx = check_index(vidx);
|
198
196
|
|
@@ -202,10 +200,8 @@ static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE b
|
|
202
200
|
}
|
203
201
|
return self;
|
204
202
|
}
|
205
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
206
203
|
|
207
|
-
static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx)
|
208
|
-
{
|
204
|
+
static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx) {
|
209
205
|
rubyDuckDBPreparedStatement *ctx;
|
210
206
|
idx_t idx = check_index(vidx);
|
211
207
|
|
@@ -216,8 +212,64 @@ static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx)
|
|
216
212
|
return self;
|
217
213
|
}
|
218
214
|
|
219
|
-
|
220
|
-
|
215
|
+
static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day) {
|
216
|
+
rubyDuckDBPreparedStatement *ctx;
|
217
|
+
duckdb_date dt;
|
218
|
+
idx_t idx = check_index(vidx);
|
219
|
+
|
220
|
+
dt = to_duckdb_date_from_value(year, month, day);
|
221
|
+
|
222
|
+
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
223
|
+
if (duckdb_bind_date(ctx->prepared_statement, idx, dt) == DuckDBError) {
|
224
|
+
rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
|
225
|
+
}
|
226
|
+
return self;
|
227
|
+
}
|
228
|
+
|
229
|
+
static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros){
|
230
|
+
rubyDuckDBPreparedStatement *ctx;
|
231
|
+
duckdb_time time;
|
232
|
+
|
233
|
+
idx_t idx = check_index(vidx);
|
234
|
+
|
235
|
+
time = to_duckdb_time_from_value(hour, min, sec, micros);
|
236
|
+
|
237
|
+
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
238
|
+
if (duckdb_bind_time(ctx->prepared_statement, idx, time) == DuckDBError) {
|
239
|
+
rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
|
240
|
+
}
|
241
|
+
return self;
|
242
|
+
}
|
243
|
+
|
244
|
+
static VALUE duckdb_prepared_statement__bind_timestamp(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
245
|
+
duckdb_timestamp timestamp;
|
246
|
+
rubyDuckDBPreparedStatement *ctx;
|
247
|
+
idx_t idx = check_index(vidx);
|
248
|
+
|
249
|
+
timestamp = to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
|
250
|
+
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
251
|
+
|
252
|
+
if (duckdb_bind_timestamp(ctx->prepared_statement, idx, timestamp) == DuckDBError) {
|
253
|
+
rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
|
254
|
+
}
|
255
|
+
return self;
|
256
|
+
}
|
257
|
+
|
258
|
+
static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros) {
|
259
|
+
duckdb_interval interval;
|
260
|
+
rubyDuckDBPreparedStatement *ctx;
|
261
|
+
idx_t idx = check_index(vidx);
|
262
|
+
|
263
|
+
Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
|
264
|
+
to_duckdb_interval_from_value(&interval, months, days, micros);
|
265
|
+
|
266
|
+
if (duckdb_bind_interval(ctx->prepared_statement, idx, interval) == DuckDBError) {
|
267
|
+
rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
|
268
|
+
}
|
269
|
+
return self;
|
270
|
+
}
|
271
|
+
|
272
|
+
void init_duckdb_prepared_statement(void) {
|
221
273
|
cDuckDBPreparedStatement = rb_define_class_under(mDuckDB, "PreparedStatement", rb_cObject);
|
222
274
|
|
223
275
|
rb_define_alloc_func(cDuckDBPreparedStatement, allocate);
|
@@ -233,8 +285,10 @@ void init_duckdb_prepared_statement(void)
|
|
233
285
|
rb_define_method(cDuckDBPreparedStatement, "bind_float", duckdb_prepared_statement_bind_float, 2);
|
234
286
|
rb_define_method(cDuckDBPreparedStatement, "bind_double", duckdb_prepared_statement_bind_double, 2);
|
235
287
|
rb_define_method(cDuckDBPreparedStatement, "bind_varchar", duckdb_prepared_statement_bind_varchar, 2);
|
236
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
237
288
|
rb_define_method(cDuckDBPreparedStatement, "bind_blob", duckdb_prepared_statement_bind_blob, 2);
|
238
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
239
289
|
rb_define_method(cDuckDBPreparedStatement, "bind_null", duckdb_prepared_statement_bind_null, 1);
|
290
|
+
rb_define_private_method(cDuckDBPreparedStatement, "_bind_date", duckdb_prepared_statement__bind_date, 4);
|
291
|
+
rb_define_private_method(cDuckDBPreparedStatement, "_bind_time", duckdb_prepared_statement__bind_time, 5);
|
292
|
+
rb_define_private_method(cDuckDBPreparedStatement, "_bind_timestamp", duckdb_prepared_statement__bind_timestamp, 8);
|
293
|
+
rb_define_private_method(cDuckDBPreparedStatement, "_bind_interval", duckdb_prepared_statement__bind_interval, 4);
|
240
294
|
}
|
data/ext/duckdb/result.c
CHANGED
@@ -2,6 +2,22 @@
|
|
2
2
|
|
3
3
|
static VALUE cDuckDBResult;
|
4
4
|
|
5
|
+
static void deallocate(void *ctx);
|
6
|
+
static VALUE allocate(VALUE klass);
|
7
|
+
static VALUE to_ruby_obj_boolean(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
8
|
+
static VALUE to_ruby_obj_smallint(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
9
|
+
static VALUE to_ruby_obj_integer(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
10
|
+
static VALUE to_ruby_obj_bigint(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
11
|
+
static VALUE to_ruby_obj_float(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
12
|
+
static VALUE to_ruby_obj_double(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
13
|
+
static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
14
|
+
static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx);
|
15
|
+
static VALUE row_array(rubyDuckDBResult *ctx, idx_t row_idx);
|
16
|
+
static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj);
|
17
|
+
static VALUE duckdb_result_each(VALUE oDuckDBResult);
|
18
|
+
static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult);
|
19
|
+
static VALUE duckdb_result_columns(VALUE oDuckDBResult);
|
20
|
+
|
5
21
|
static void deallocate(void *ctx) {
|
6
22
|
rubyDuckDBResult *p = (rubyDuckDBResult *)ctx;
|
7
23
|
|
@@ -44,31 +60,25 @@ static VALUE to_ruby_obj_double(duckdb_result *result, idx_t col_idx, idx_t row_
|
|
44
60
|
return DBL2NUM(dval);
|
45
61
|
}
|
46
62
|
|
47
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
48
63
|
static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
|
49
64
|
VALUE str;
|
50
65
|
duckdb_blob bval = duckdb_value_blob(result, col_idx, row_idx);
|
51
66
|
str = rb_str_new(bval.data, bval.size);
|
52
67
|
|
53
68
|
if (bval.data) {
|
54
|
-
#ifdef HAVE_DUCKDB_FREE
|
55
69
|
duckdb_free(bval.data);
|
56
|
-
#else
|
57
|
-
free(bval.data);
|
58
|
-
#endif
|
59
70
|
}
|
60
71
|
|
61
72
|
return str;
|
62
73
|
}
|
63
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
64
74
|
|
65
75
|
static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
|
66
76
|
char *p;
|
67
77
|
VALUE obj = Qnil;
|
68
|
-
if (result
|
78
|
+
if (duckdb_value_is_null(result, col_idx, row_idx)) {
|
69
79
|
return obj;
|
70
80
|
}
|
71
|
-
switch(result
|
81
|
+
switch(duckdb_column_type(result, col_idx)) {
|
72
82
|
case DUCKDB_TYPE_BOOLEAN:
|
73
83
|
return to_ruby_obj_boolean(result, col_idx, row_idx);
|
74
84
|
case DUCKDB_TYPE_SMALLINT:
|
@@ -81,20 +91,14 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
|
|
81
91
|
return to_ruby_obj_float(result, col_idx, row_idx);
|
82
92
|
case DUCKDB_TYPE_DOUBLE:
|
83
93
|
return to_ruby_obj_double(result, col_idx, row_idx);
|
84
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
85
94
|
case DUCKDB_TYPE_BLOB:
|
86
95
|
return to_ruby_obj_string_from_blob(result, col_idx, row_idx);
|
87
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
88
96
|
default:
|
89
97
|
p = duckdb_value_varchar(result, col_idx, row_idx);
|
90
98
|
if (p) {
|
91
99
|
obj = rb_str_new2(p);
|
92
|
-
#ifdef HAVE_DUCKDB_FREE
|
93
100
|
duckdb_free(p);
|
94
|
-
|
95
|
-
free(p);
|
96
|
-
#endif /* HAVE_DUCKDB_FREE */
|
97
|
-
if (result->columns[col_idx].type == DUCKDB_TYPE_HUGEINT) {
|
101
|
+
if (duckdb_column_type(result, col_idx) == DUCKDB_TYPE_HUGEINT) {
|
98
102
|
obj = rb_funcall(obj, rb_intern("to_i"), 0);
|
99
103
|
}
|
100
104
|
}
|
@@ -104,8 +108,10 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
|
|
104
108
|
|
105
109
|
static VALUE row_array(rubyDuckDBResult *ctx, idx_t row_idx) {
|
106
110
|
idx_t col_idx;
|
107
|
-
|
108
|
-
|
111
|
+
idx_t column_count = duckdb_column_count(&(ctx->result));
|
112
|
+
|
113
|
+
VALUE ary = rb_ary_new2(column_count);
|
114
|
+
for(col_idx = 0; col_idx < column_count; col_idx++) {
|
109
115
|
rb_ary_store(ary, col_idx, to_ruby_obj(&(ctx->result), col_idx, row_idx));
|
110
116
|
}
|
111
117
|
return ary;
|
@@ -115,17 +121,19 @@ static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj)
|
|
115
121
|
rubyDuckDBResult *ctx;
|
116
122
|
Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
|
117
123
|
|
118
|
-
return LONG2FIX(ctx->result
|
124
|
+
return LONG2FIX(duckdb_row_count(&(ctx->result)));
|
119
125
|
}
|
120
126
|
|
121
127
|
static VALUE duckdb_result_each(VALUE oDuckDBResult) {
|
122
128
|
rubyDuckDBResult *ctx;
|
123
129
|
idx_t row_idx = 0;
|
130
|
+
idx_t row_count = 0;
|
124
131
|
|
125
132
|
RETURN_SIZED_ENUMERATOR(oDuckDBResult, 0, 0, duckdb_result_row_size);
|
126
133
|
|
127
134
|
Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
|
128
|
-
|
135
|
+
row_count = duckdb_row_count(&(ctx->result));
|
136
|
+
for (row_idx = 0; row_idx < row_count; row_idx++) {
|
129
137
|
rb_yield(row_array(ctx, row_idx));
|
130
138
|
}
|
131
139
|
return oDuckDBResult;
|
@@ -156,7 +164,29 @@ static VALUE duckdb_result_each(VALUE oDuckDBResult) {
|
|
156
164
|
static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult) {
|
157
165
|
rubyDuckDBResult *ctx;
|
158
166
|
Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
|
159
|
-
return LL2NUM(ctx->result
|
167
|
+
return LL2NUM(duckdb_rows_changed(&(ctx->result)));
|
168
|
+
}
|
169
|
+
|
170
|
+
/*
|
171
|
+
* call-seq:
|
172
|
+
* result.columns -> DuckDB::Column[]
|
173
|
+
*
|
174
|
+
* Returns the column class Lists.
|
175
|
+
*
|
176
|
+
*/
|
177
|
+
static VALUE duckdb_result_columns(VALUE oDuckDBResult) {
|
178
|
+
rubyDuckDBResult *ctx;
|
179
|
+
Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
|
180
|
+
|
181
|
+
idx_t col_idx;
|
182
|
+
idx_t column_count = duckdb_column_count(&(ctx->result));
|
183
|
+
|
184
|
+
VALUE ary = rb_ary_new2(column_count);
|
185
|
+
for(col_idx = 0; col_idx < column_count; col_idx++) {
|
186
|
+
VALUE column = create_column(oDuckDBResult, col_idx);
|
187
|
+
rb_ary_store(ary, col_idx, column);
|
188
|
+
}
|
189
|
+
return ary;
|
160
190
|
}
|
161
191
|
|
162
192
|
VALUE create_result(void) {
|
@@ -169,4 +199,5 @@ void init_duckdb_result(void) {
|
|
169
199
|
|
170
200
|
rb_define_method(cDuckDBResult, "each", duckdb_result_each, 0);
|
171
201
|
rb_define_method(cDuckDBResult, "rows_changed", duckdb_result_rows_changed, 0);
|
202
|
+
rb_define_method(cDuckDBResult, "columns", duckdb_result_columns, 0);
|
172
203
|
}
|
data/ext/duckdb/ruby-duckdb.h
CHANGED
@@ -3,24 +3,22 @@
|
|
3
3
|
|
4
4
|
#include "ruby.h"
|
5
5
|
#include <duckdb.h>
|
6
|
+
|
7
|
+
#ifdef HAVE_DUCKDB_APPEND_DATA_CHUNK
|
8
|
+
#define HAVE_DUCKDB_H_GE_V033 1
|
9
|
+
#endif
|
10
|
+
|
6
11
|
#include "./error.h"
|
7
12
|
#include "./database.h"
|
8
13
|
#include "./connection.h"
|
9
14
|
#include "./result.h"
|
15
|
+
#include "./column.h"
|
10
16
|
#include "./prepared_statement.h"
|
11
|
-
|
12
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
17
|
+
#include "./util.h"
|
13
18
|
|
14
19
|
#include "./blob.h"
|
15
|
-
|
16
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
17
|
-
|
18
|
-
#ifdef HAVE_DUCKDB_APPENDER_CREATE
|
19
|
-
|
20
20
|
#include "./appender.h"
|
21
21
|
|
22
|
-
#endif /* HAVE_DUCKDB_APPENDER_CREATE */
|
23
|
-
|
24
22
|
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
25
23
|
|
26
24
|
#include "./config.h"
|
@@ -30,19 +28,8 @@
|
|
30
28
|
extern VALUE mDuckDB;
|
31
29
|
extern VALUE cDuckDBDatabase;
|
32
30
|
extern VALUE cDuckDBConnection;
|
33
|
-
|
34
|
-
#ifdef HAVE_DUCKDB_VALUE_BLOB
|
35
|
-
|
36
31
|
extern VALUE cDuckDBBlob;
|
37
|
-
|
38
|
-
#endif /* HAVE_DUCKDB_VALUE_BLOB */
|
39
|
-
|
40
|
-
#ifdef HAVE_DUCKDB_CREATE_CONFIG
|
41
|
-
|
42
32
|
extern VALUE cDuckDBConfig;
|
43
|
-
|
44
|
-
#endif /* HAVE_DUCKDB_CREATE_CONFIG */
|
45
|
-
|
46
33
|
extern VALUE eDuckDBError;
|
47
34
|
|
48
35
|
#endif
|
data/ext/duckdb/util.c
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
#include "ruby-duckdb.h"
|
2
|
+
|
3
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
4
|
+
|
5
|
+
duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day) {
|
6
|
+
duckdb_date_struct dt_struct;
|
7
|
+
|
8
|
+
dt_struct.year = NUM2INT(year);
|
9
|
+
dt_struct.month = NUM2INT(month);
|
10
|
+
dt_struct.day = NUM2INT(day);
|
11
|
+
|
12
|
+
return duckdb_to_date(dt_struct);
|
13
|
+
}
|
14
|
+
|
15
|
+
duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
16
|
+
duckdb_time_struct time_st;
|
17
|
+
|
18
|
+
time_st.hour = NUM2INT(hour);
|
19
|
+
time_st.min = NUM2INT(min);
|
20
|
+
time_st.sec = NUM2INT(sec);
|
21
|
+
time_st.micros = NUM2INT(micros);
|
22
|
+
|
23
|
+
return duckdb_to_time(time_st);
|
24
|
+
}
|
25
|
+
|
26
|
+
duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros) {
|
27
|
+
duckdb_timestamp_struct timestamp_st;
|
28
|
+
|
29
|
+
timestamp_st.date.year = NUM2INT(year);
|
30
|
+
timestamp_st.date.month = NUM2INT(month);
|
31
|
+
timestamp_st.date.day = NUM2INT(day);
|
32
|
+
timestamp_st.time.hour = NUM2INT(hour);
|
33
|
+
timestamp_st.time.min = NUM2INT(min);
|
34
|
+
timestamp_st.time.sec = NUM2INT(sec);
|
35
|
+
timestamp_st.time.micros = NUM2INT(micros);
|
36
|
+
|
37
|
+
return duckdb_to_timestamp(timestamp_st);
|
38
|
+
}
|
39
|
+
|
40
|
+
void to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros) {
|
41
|
+
interval->months = NUM2INT(months);
|
42
|
+
interval->days = NUM2INT(days);
|
43
|
+
interval->micros = NUM2LL(micros);
|
44
|
+
}
|
45
|
+
#endif
|
data/ext/duckdb/util.h
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#ifndef RUBY_DUCKDB_UTIL_H
|
2
|
+
#define RUBY_DUCKDB_UTIL_H
|
3
|
+
|
4
|
+
#ifdef HAVE_DUCKDB_APPEND_DATE
|
5
|
+
|
6
|
+
duckdb_date to_duckdb_date_from_value(VALUE year, VALUE month, VALUE day);
|
7
|
+
duckdb_time to_duckdb_time_from_value(VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
8
|
+
duckdb_timestamp to_duckdb_timestamp_from_value(VALUE year, VALUE month, VALUE day, VALUE hour, VALUE min, VALUE sec, VALUE micros);
|
9
|
+
void to_duckdb_interval_from_value(duckdb_interval* interval, VALUE months, VALUE days, VALUE micros);
|
10
|
+
|
11
|
+
#endif
|
12
|
+
|
13
|
+
#endif
|