duckdb 0.3.1.0 → 0.3.4.0
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 +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
|