duckdb 0.2.9.0 → 0.3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -7,28 +7,26 @@ static void deallocate(void * ctx);
7
7
  static VALUE allocate(VALUE klass);
8
8
  static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase);
9
9
  static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBDatabase);
10
+ static VALUE duckdb_database_connect(VALUE self);
11
+ static VALUE duckdb_database_close(VALUE self);
10
12
 
11
- static void close_database(rubyDuckDB *p)
12
- {
13
+ static void close_database(rubyDuckDB *p) {
13
14
  duckdb_close(&(p->db));
14
15
  }
15
16
 
16
- static void deallocate(void * ctx)
17
- {
17
+ static void deallocate(void * ctx) {
18
18
  rubyDuckDB *p = (rubyDuckDB *)ctx;
19
19
 
20
20
  close_database(p);
21
21
  xfree(p);
22
22
  }
23
23
 
24
- static VALUE allocate(VALUE klass)
25
- {
24
+ static VALUE allocate(VALUE klass) {
26
25
  rubyDuckDB *ctx = xcalloc((size_t)1, sizeof(rubyDuckDB));
27
26
  return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
28
27
  }
29
28
 
30
- static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase)
31
- {
29
+ static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase) {
32
30
  rubyDuckDB *ctx;
33
31
  VALUE obj;
34
32
 
@@ -50,8 +48,7 @@ static VALUE duckdb_database_s_open(int argc, VALUE *argv, VALUE cDuckDBDatabase
50
48
  }
51
49
 
52
50
  #ifdef HAVE_DUCKDB_OPEN_EXT
53
- static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBDatabase)
54
- {
51
+ static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBDatabase) {
55
52
  rubyDuckDB *ctx;
56
53
  VALUE obj;
57
54
  rubyDuckDBConfig *ctx_config;
@@ -86,8 +83,7 @@ static VALUE duckdb_database_s_open_ext(int argc, VALUE *argv, VALUE cDuckDBData
86
83
  }
87
84
  #endif /* HAVE_DUCKDB_OPEN_EXT */
88
85
 
89
- static VALUE duckdb_database_connect(VALUE self)
90
- {
86
+ static VALUE duckdb_database_connect(VALUE self) {
91
87
  return create_connection(self);
92
88
  }
93
89
 
@@ -97,16 +93,14 @@ static VALUE duckdb_database_connect(VALUE self)
97
93
  *
98
94
  * closes DuckDB database.
99
95
  */
100
- static VALUE duckdb_database_close(VALUE self)
101
- {
96
+ static VALUE duckdb_database_close(VALUE self) {
102
97
  rubyDuckDB *ctx;
103
98
  Data_Get_Struct(self, rubyDuckDB, ctx);
104
99
  close_database(ctx);
105
100
  return self;
106
101
  }
107
102
 
108
- void init_duckdb_database(void)
109
- {
103
+ void init_duckdb_database(void) {
110
104
  cDuckDBDatabase = rb_define_class_under(mDuckDB, "Database", rb_cObject);
111
105
  rb_define_alloc_func(cDuckDBDatabase, allocate);
112
106
  rb_define_singleton_method(cDuckDBDatabase, "_open", duckdb_database_s_open, -1);
data/ext/duckdb/duckdb.c CHANGED
@@ -3,28 +3,19 @@
3
3
  VALUE mDuckDB;
4
4
 
5
5
  void
6
- Init_duckdb_native(void)
7
- {
6
+ Init_duckdb_native(void) {
8
7
  mDuckDB = rb_define_module("DuckDB");
9
8
 
10
9
  init_duckdb_error();
11
10
  init_duckdb_database();
12
11
  init_duckdb_connection();
13
12
  init_duckdb_result();
13
+ init_duckdb_column();
14
14
  init_duckdb_prepared_statement();
15
-
16
- #ifdef HAVE_DUCKDB_VALUE_BLOB
17
-
18
15
  init_duckdb_blob();
19
16
 
20
- #endif /* HAVE_DUCKDB_VALUE_BLOB */
21
-
22
- #ifdef HAVE_DUCKDB_APPENDER_CREATE
23
-
24
17
  init_duckdb_appender();
25
18
 
26
- #endif /* HAVE_DUCKDB_APPENDER_CREATE */
27
-
28
19
  #ifdef HAVE_DUCKDB_CREATE_CONFIG
29
20
 
30
21
  init_duckdb_config();
data/ext/duckdb/error.c CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  VALUE eDuckDBError;
4
4
 
5
- void init_duckdb_error(void)
6
- {
5
+ void init_duckdb_error(void) {
7
6
  eDuckDBError = rb_define_class_under(mDuckDB, "Error", rb_eStandardError);
8
7
  }
@@ -1,24 +1,20 @@
1
1
  require 'mkmf'
2
2
 
3
3
  dir_config('duckdb')
4
- if have_library('duckdb')
5
- if have_func('duckdb_nparams(NULL)', 'duckdb.h')
6
- $defs << '-DHAVE_DUCKDB_NPARAMS_029'
7
- elsif have_func('duckdb_nparams(NULL, NULL)', 'duckdb.h')
8
- $defs << '-DHAVE_DUCKDB_NPARAMS_028'
9
- end
10
-
11
- have_func('duckdb_value_blob', 'duckdb.h')
12
- have_func('duckdb_bind_blob', 'duckdb.h')
13
- have_func('duckdb_appender_create', 'duckdb.h')
14
- have_func('duckdb_free', 'duckdb.h')
15
- have_func('duckdb_create_config', 'duckdb.h')
16
- have_func('duckdb_open_ext', 'duckdb.h')
17
- have_func('duckdb_prepare_error', 'duckdb.h')
18
- have_func('duckdb_append_date', 'duckdb.h')
19
- have_func('duckdb_append_interval', 'duckdb.h')
20
- have_func('duckdb_append_time', 'duckdb.h')
21
- have_func('duckdb_append_timestamp', 'duckdb.h')
22
- have_func('duckdb_append_hugeint', 'duckdb.h')
23
- create_makefile('duckdb/duckdb_native')
24
- end
4
+
5
+ raise 'duckdb library is not found. Install duckdb library file and header file.' unless have_library('duckdb')
6
+
7
+ raise 'duckdb >= 0.2.9 is required. Install duckdb >= 0.2.9' unless have_func('duckdb_value_is_null', 'duckdb.h')
8
+
9
+ # ducdb >= 0.3.3 if duckdb_append_data_chunk() is defined.
10
+ have_func('duckdb_append_data_chunk', 'duckdb.h')
11
+
12
+ have_func('duckdb_free', 'duckdb.h')
13
+
14
+ have_func('duckdb_create_config', 'duckdb.h')
15
+ have_func('duckdb_open_ext', 'duckdb.h')
16
+ have_func('duckdb_prepare_error', 'duckdb.h')
17
+
18
+ have_func('duckdb_append_date', 'duckdb.h')
19
+
20
+ create_makefile('duckdb/duckdb_native')
@@ -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.error_message);
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
- #ifdef HAVE_DUCKDB_VALUE_BLOB
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
- void init_duckdb_prepared_statement(void)
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->columns[col_idx].nullmask[row_idx]) {
78
+ if (duckdb_value_is_null(result, col_idx, row_idx)) {
69
79
  return obj;
70
80
  }
71
- switch(result->columns[col_idx].type) {
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
- #else
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
- VALUE ary = rb_ary_new2(ctx->result.column_count);
108
- for(col_idx = 0; col_idx < ctx->result.column_count; col_idx++) {
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.row_count);
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
- for (row_idx = 0; row_idx < ctx->result.row_count; row_idx++) {
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.rows_changed);
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
  }
@@ -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_HEADER_VERSION_033 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