duckdb 0.2.8.0 → 0.3.2.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,8 +3,7 @@
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();
@@ -12,13 +11,8 @@ Init_duckdb_native(void)
12
11
  init_duckdb_connection();
13
12
  init_duckdb_result();
14
13
  init_duckdb_prepared_statement();
15
-
16
- #ifdef HAVE_DUCKDB_VALUE_BLOB
17
-
18
14
  init_duckdb_blob();
19
15
 
20
- #endif /* HAVE_DUCKDB_VALUE_BLOB */
21
-
22
16
  #ifdef HAVE_DUCKDB_APPENDER_CREATE
23
17
 
24
18
  init_duckdb_appender();
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,12 +1,33 @@
1
1
  require 'mkmf'
2
2
 
3
3
  dir_config('duckdb')
4
- if have_library('duckdb')
5
- have_func('duckdb_value_blob', 'duckdb.h')
6
- have_func('duckdb_bind_blob', 'duckdb.h')
7
- have_func('duckdb_appender_create', 'duckdb.h')
8
- have_func('duckdb_free', 'duckdb.h')
9
- have_func('duckdb_create_config', 'duckdb.h')
10
- have_func('duckdb_open_ext', 'duckdb.h')
11
- create_makefile('duckdb/duckdb_native')
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
+ if have_func('duckdb_nparams(NULL)', 'duckdb.h')
10
+ $defs << '-DHAVE_DUCKDB_NPARAMS_029'
11
+ elsif have_func('duckdb_nparams(NULL, NULL)', 'duckdb.h')
12
+ $defs << '-DHAVE_DUCKDB_NPARAMS_028'
12
13
  end
14
+
15
+ have_func('duckdb_appender_create', 'duckdb.h')
16
+ have_func('duckdb_free', 'duckdb.h')
17
+
18
+ have_func('duckdb_create_config', 'duckdb.h')
19
+ have_func('duckdb_open_ext', 'duckdb.h')
20
+ have_func('duckdb_prepare_error', 'duckdb.h')
21
+
22
+ have_func('duckdb_append_date', 'duckdb.h')
23
+ have_func('duckdb_append_interval', 'duckdb.h')
24
+ have_func('duckdb_append_time', 'duckdb.h')
25
+ have_func('duckdb_append_timestamp', 'duckdb.h')
26
+ have_func('duckdb_append_hugeint', 'duckdb.h')
27
+
28
+ have_func('duckdb_bind_date', 'duckdb.h')
29
+ have_func('duckdb_bind_time', 'duckdb.h')
30
+ have_func('duckdb_bind_timestamp', 'duckdb.h')
31
+ have_func('duckdb_bind_interval', 'duckdb.h')
32
+
33
+ create_makefile('duckdb/duckdb_native')
@@ -2,22 +2,53 @@
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
+
22
+ #ifdef HAVE_DUCKDB_BIND_DATE
23
+ static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day);
24
+ #endif
25
+
26
+ #ifdef HAVE_DUCKDB_BIND_TIME
27
+ static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros);
28
+ #endif
29
+
30
+ #ifdef HAVE_DUCKDB_BIND_TIMESTAMP
31
+ 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);
32
+ #endif
33
+
34
+ #ifdef HAVE_DUCKDB_BIND_INTERVAL
35
+ static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros);
36
+ #endif
37
+
38
+
39
+ static void deallocate(void *ctx) {
7
40
  rubyDuckDBPreparedStatement *p = (rubyDuckDBPreparedStatement *)ctx;
8
41
 
9
42
  duckdb_destroy_prepare(&(p->prepared_statement));
10
43
  xfree(p);
11
44
  }
12
45
 
13
- static VALUE allocate(VALUE klass)
14
- {
46
+ static VALUE allocate(VALUE klass) {
15
47
  rubyDuckDBPreparedStatement *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBPreparedStatement));
16
48
  return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
17
49
  }
18
50
 
19
- static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query)
20
- {
51
+ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE query) {
21
52
  rubyDuckDBConnection *ctxcon;
22
53
  rubyDuckDBPreparedStatement *ctx;
23
54
 
@@ -29,26 +60,32 @@ static VALUE duckdb_prepared_statement_initialize(VALUE self, VALUE con, VALUE q
29
60
  Data_Get_Struct(con, rubyDuckDBConnection, ctxcon);
30
61
 
31
62
  if (duckdb_prepare(ctxcon->con, StringValuePtr(query), &(ctx->prepared_statement)) == DuckDBError) {
63
+ #ifdef HAVE_DUCKDB_PREPARE_ERROR
64
+ const char *error = duckdb_prepare_error(ctx->prepared_statement);
65
+ rb_raise(eDuckDBError, "%s", error);
66
+ #else
32
67
  /* TODO: include query parameter information in error message. */
33
68
  rb_raise(eDuckDBError, "failed to prepare statement");
69
+ #endif
34
70
  }
35
71
  return self;
36
72
  }
37
73
 
38
- static VALUE duckdb_prepared_statement_nparams(VALUE self)
39
- {
74
+ static VALUE duckdb_prepared_statement_nparams(VALUE self) {
40
75
  rubyDuckDBPreparedStatement *ctx;
41
76
  Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
42
-
77
+ #ifdef HAVE_DUCKDB_NPARAMS_029
78
+ return rb_int2big(duckdb_nparams(ctx->prepared_statement));
79
+ #else
43
80
  if (duckdb_nparams(ctx->prepared_statement, &(ctx->nparams)) == DuckDBError) {
44
81
  rb_raise(eDuckDBError, "failed to get number of parameters");
45
82
  }
46
83
  return rb_int2big(ctx->nparams);
84
+ #endif
47
85
  }
48
86
 
49
87
 
50
- static VALUE duckdb_prepared_statement_execute(VALUE self)
51
- {
88
+ static VALUE duckdb_prepared_statement_execute(VALUE self) {
52
89
  rubyDuckDBPreparedStatement *ctx;
53
90
  rubyDuckDBResult *ctxr;
54
91
  VALUE result = create_result();
@@ -56,13 +93,12 @@ static VALUE duckdb_prepared_statement_execute(VALUE self)
56
93
  Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
57
94
  Data_Get_Struct(result, rubyDuckDBResult, ctxr);
58
95
  if (duckdb_execute_prepared(ctx->prepared_statement, &(ctxr->result)) == DuckDBError) {
59
- rb_raise(eDuckDBError, "%s", ctxr->result.error_message);
96
+ rb_raise(eDuckDBError, "%s", duckdb_result_error(&(ctxr->result)));
60
97
  }
61
98
  return result;
62
99
  }
63
100
 
64
- static idx_t check_index(VALUE vidx)
65
- {
101
+ static idx_t check_index(VALUE vidx) {
66
102
  idx_t idx = FIX2INT(vidx);
67
103
  if (idx <= 0) {
68
104
  rb_raise(rb_eArgError, "index of parameter must be greater than 0");
@@ -70,8 +106,7 @@ static idx_t check_index(VALUE vidx)
70
106
  return idx;
71
107
  }
72
108
 
73
- static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val)
74
- {
109
+ static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE val) {
75
110
  rubyDuckDBPreparedStatement *ctx;
76
111
  idx_t idx = check_index(vidx);
77
112
 
@@ -86,8 +121,7 @@ static VALUE duckdb_prepared_statement_bind_bool(VALUE self, VALUE vidx, VALUE v
86
121
  return self;
87
122
  }
88
123
 
89
- static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val)
90
- {
124
+ static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE val) {
91
125
  rubyDuckDBPreparedStatement *ctx;
92
126
  idx_t idx = check_index(vidx);
93
127
  int8_t i8val = (int8_t)NUM2INT(val);
@@ -100,8 +134,7 @@ static VALUE duckdb_prepared_statement_bind_int8(VALUE self, VALUE vidx, VALUE v
100
134
  return self;
101
135
  }
102
136
 
103
- static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val)
104
- {
137
+ static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE val) {
105
138
  rubyDuckDBPreparedStatement *ctx;
106
139
  idx_t idx = check_index(vidx);
107
140
  int16_t i16val = NUM2INT(val);
@@ -114,8 +147,7 @@ static VALUE duckdb_prepared_statement_bind_int16(VALUE self, VALUE vidx, VALUE
114
147
  return self;
115
148
  }
116
149
 
117
- static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE val)
118
- {
150
+ static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE val) {
119
151
  rubyDuckDBPreparedStatement *ctx;
120
152
  idx_t idx = check_index(vidx);
121
153
  int32_t i32val = NUM2INT(val);
@@ -128,8 +160,7 @@ static VALUE duckdb_prepared_statement_bind_int32(VALUE self, VALUE vidx, VALUE
128
160
  return self;
129
161
  }
130
162
 
131
- static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE val)
132
- {
163
+ static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE val) {
133
164
  rubyDuckDBPreparedStatement *ctx;
134
165
  idx_t idx = check_index(vidx);
135
166
  int64_t i64val = NUM2LL(val);
@@ -142,8 +173,7 @@ static VALUE duckdb_prepared_statement_bind_int64(VALUE self, VALUE vidx, VALUE
142
173
  return self;
143
174
  }
144
175
 
145
- static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE val)
146
- {
176
+ static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE val) {
147
177
  rubyDuckDBPreparedStatement *ctx;
148
178
  idx_t idx = check_index(vidx);
149
179
  double dbl = NUM2DBL(val);
@@ -156,8 +186,7 @@ static VALUE duckdb_prepared_statement_bind_float(VALUE self, VALUE vidx, VALUE
156
186
  return self;
157
187
  }
158
188
 
159
- static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE val)
160
- {
189
+ static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE val) {
161
190
  rubyDuckDBPreparedStatement *ctx;
162
191
  idx_t idx = check_index(vidx);
163
192
  double dbl = NUM2DBL(val);
@@ -170,8 +199,7 @@ static VALUE duckdb_prepared_statement_bind_double(VALUE self, VALUE vidx, VALUE
170
199
  return self;
171
200
  }
172
201
 
173
- static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str)
174
- {
202
+ static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALUE str) {
175
203
  rubyDuckDBPreparedStatement *ctx;
176
204
  idx_t idx = check_index(vidx);
177
205
 
@@ -182,9 +210,7 @@ static VALUE duckdb_prepared_statement_bind_varchar(VALUE self, VALUE vidx, VALU
182
210
  return self;
183
211
  }
184
212
 
185
- #ifdef HAVE_DUCKDB_VALUE_BLOB
186
- static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob)
187
- {
213
+ static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE blob) {
188
214
  rubyDuckDBPreparedStatement *ctx;
189
215
  idx_t idx = check_index(vidx);
190
216
 
@@ -194,10 +220,8 @@ static VALUE duckdb_prepared_statement_bind_blob(VALUE self, VALUE vidx, VALUE b
194
220
  }
195
221
  return self;
196
222
  }
197
- #endif /* HAVE_DUCKDB_VALUE_BLOB */
198
223
 
199
- static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx)
200
- {
224
+ static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx) {
201
225
  rubyDuckDBPreparedStatement *ctx;
202
226
  idx_t idx = check_index(vidx);
203
227
 
@@ -208,8 +232,72 @@ static VALUE duckdb_prepared_statement_bind_null(VALUE self, VALUE vidx)
208
232
  return self;
209
233
  }
210
234
 
211
- void init_duckdb_prepared_statement(void)
212
- {
235
+ #ifdef HAVE_DUCKDB_BIND_DATE
236
+ static VALUE duckdb_prepared_statement__bind_date(VALUE self, VALUE vidx, VALUE year, VALUE month, VALUE day) {
237
+ rubyDuckDBPreparedStatement *ctx;
238
+ duckdb_date dt;
239
+ idx_t idx = check_index(vidx);
240
+
241
+ dt = to_duckdb_date_from_value(year, month, day);
242
+
243
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
244
+ if (duckdb_bind_date(ctx->prepared_statement, idx, dt) == DuckDBError) {
245
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
246
+ }
247
+ return self;
248
+ }
249
+ #endif
250
+
251
+ #ifdef HAVE_DUCKDB_BIND_TIME
252
+ static VALUE duckdb_prepared_statement__bind_time(VALUE self, VALUE vidx, VALUE hour, VALUE min, VALUE sec, VALUE micros){
253
+ rubyDuckDBPreparedStatement *ctx;
254
+ duckdb_time time;
255
+
256
+ idx_t idx = check_index(vidx);
257
+
258
+ time = to_duckdb_time_from_value(hour, min, sec, micros);
259
+
260
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
261
+ if (duckdb_bind_time(ctx->prepared_statement, idx, time) == DuckDBError) {
262
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
263
+ }
264
+ return self;
265
+ }
266
+ #endif
267
+
268
+ #ifdef HAVE_DUCKDB_BIND_TIMESTAMP
269
+ 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) {
270
+ duckdb_timestamp timestamp;
271
+ rubyDuckDBPreparedStatement *ctx;
272
+ idx_t idx = check_index(vidx);
273
+
274
+ timestamp = to_duckdb_timestamp_from_value(year, month, day, hour, min, sec, micros);
275
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
276
+
277
+ if (duckdb_bind_timestamp(ctx->prepared_statement, idx, timestamp) == DuckDBError) {
278
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
279
+ }
280
+ return self;
281
+ }
282
+ #endif
283
+
284
+ #ifdef HAVE_DUCKDB_BIND_INTERVAL
285
+ static VALUE duckdb_prepared_statement__bind_interval(VALUE self, VALUE vidx, VALUE months, VALUE days, VALUE micros) {
286
+ duckdb_interval interval;
287
+ rubyDuckDBPreparedStatement *ctx;
288
+ idx_t idx = check_index(vidx);
289
+
290
+ Data_Get_Struct(self, rubyDuckDBPreparedStatement, ctx);
291
+ to_duckdb_interval_from_value(&interval, months, days, micros);
292
+
293
+ if (duckdb_bind_interval(ctx->prepared_statement, idx, interval) == DuckDBError) {
294
+ rb_raise(eDuckDBError, "fail to bind %llu parameter", (unsigned long long)idx);
295
+ }
296
+ return self;
297
+ }
298
+ #endif
299
+
300
+ void init_duckdb_prepared_statement(void) {
213
301
  cDuckDBPreparedStatement = rb_define_class_under(mDuckDB, "PreparedStatement", rb_cObject);
214
302
 
215
303
  rb_define_alloc_func(cDuckDBPreparedStatement, allocate);
@@ -225,8 +313,16 @@ void init_duckdb_prepared_statement(void)
225
313
  rb_define_method(cDuckDBPreparedStatement, "bind_float", duckdb_prepared_statement_bind_float, 2);
226
314
  rb_define_method(cDuckDBPreparedStatement, "bind_double", duckdb_prepared_statement_bind_double, 2);
227
315
  rb_define_method(cDuckDBPreparedStatement, "bind_varchar", duckdb_prepared_statement_bind_varchar, 2);
228
- #ifdef HAVE_DUCKDB_VALUE_BLOB
229
316
  rb_define_method(cDuckDBPreparedStatement, "bind_blob", duckdb_prepared_statement_bind_blob, 2);
230
- #endif /* HAVE_DUCKDB_VALUE_BLOB */
231
317
  rb_define_method(cDuckDBPreparedStatement, "bind_null", duckdb_prepared_statement_bind_null, 1);
318
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_date", duckdb_prepared_statement__bind_date, 4);
319
+ #ifdef HAVE_DUCKDB_BIND_TIME
320
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_time", duckdb_prepared_statement__bind_time, 5);
321
+ #endif
322
+ #ifdef HAVE_DUCKDB_BIND_TIMESTAMP
323
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_timestamp", duckdb_prepared_statement__bind_timestamp, 8);
324
+ #endif
325
+ #ifdef HAVE_DUCKDB_BIND_INTERVAL
326
+ rb_define_private_method(cDuckDBPreparedStatement, "_bind_interval", duckdb_prepared_statement__bind_interval, 4);
327
+ #endif
232
328
  }
data/ext/duckdb/result.c CHANGED
@@ -2,59 +2,64 @@
2
2
 
3
3
  static VALUE cDuckDBResult;
4
4
 
5
- static void deallocate(void *ctx)
6
- {
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
+
20
+ static void deallocate(void *ctx) {
7
21
  rubyDuckDBResult *p = (rubyDuckDBResult *)ctx;
8
22
 
9
23
  duckdb_destroy_result(&(p->result));
10
24
  xfree(p);
11
25
  }
12
26
 
13
- static VALUE allocate(VALUE klass)
14
- {
27
+ static VALUE allocate(VALUE klass) {
15
28
  rubyDuckDBResult *ctx = xcalloc((size_t)1, sizeof(rubyDuckDBResult));
16
29
  return Data_Wrap_Struct(klass, NULL, deallocate, ctx);
17
30
  }
18
31
 
19
- static VALUE to_ruby_obj_boolean(duckdb_result *result, idx_t col_idx, idx_t row_idx)
20
- {
32
+ static VALUE to_ruby_obj_boolean(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
21
33
  bool bval = duckdb_value_boolean(result, col_idx, row_idx);
22
34
  return bval ? Qtrue : Qnil;
23
35
  }
24
36
 
25
- static VALUE to_ruby_obj_smallint(duckdb_result *result, idx_t col_idx, idx_t row_idx)
26
- {
37
+ static VALUE to_ruby_obj_smallint(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
27
38
  int16_t i16val = duckdb_value_int16(result, col_idx, row_idx);
28
39
  return INT2FIX(i16val);
29
40
  }
30
41
 
31
- static VALUE to_ruby_obj_integer(duckdb_result *result, idx_t col_idx, idx_t row_idx)
32
- {
42
+ static VALUE to_ruby_obj_integer(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
33
43
  int32_t i32val = duckdb_value_int32(result, col_idx, row_idx);
34
44
  return INT2NUM(i32val);
35
45
  }
36
46
 
37
- static VALUE to_ruby_obj_bigint(duckdb_result *result, idx_t col_idx, idx_t row_idx)
38
- {
47
+ static VALUE to_ruby_obj_bigint(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
39
48
  int64_t i64val = duckdb_value_int64(result, col_idx, row_idx);
40
49
  return rb_int2big(i64val);
41
50
  }
42
51
 
43
- static VALUE to_ruby_obj_float(duckdb_result *result, idx_t col_idx, idx_t row_idx)
44
- {
52
+ static VALUE to_ruby_obj_float(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
45
53
  float fval = duckdb_value_float(result, col_idx, row_idx);
46
54
  return DBL2NUM(fval);
47
55
  }
48
56
 
49
- static VALUE to_ruby_obj_double(duckdb_result *result, idx_t col_idx, idx_t row_idx)
50
- {
57
+ static VALUE to_ruby_obj_double(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
51
58
  double dval = duckdb_value_double(result, col_idx, row_idx);
52
59
  return DBL2NUM(dval);
53
60
  }
54
61
 
55
- #ifdef HAVE_DUCKDB_VALUE_BLOB
56
- static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx, idx_t row_idx)
57
- {
62
+ static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
58
63
  VALUE str;
59
64
  duckdb_blob bval = duckdb_value_blob(result, col_idx, row_idx);
60
65
  str = rb_str_new(bval.data, bval.size);
@@ -69,16 +74,14 @@ static VALUE to_ruby_obj_string_from_blob(duckdb_result *result, idx_t col_idx,
69
74
 
70
75
  return str;
71
76
  }
72
- #endif /* HAVE_DUCKDB_VALUE_BLOB */
73
77
 
74
- static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
75
- {
78
+ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx) {
76
79
  char *p;
77
80
  VALUE obj = Qnil;
78
- if (result->columns[col_idx].nullmask[row_idx]) {
81
+ if (duckdb_value_is_null(result, col_idx, row_idx)) {
79
82
  return obj;
80
83
  }
81
- switch(result->columns[col_idx].type) {
84
+ switch(duckdb_column_type(result, col_idx)) {
82
85
  case DUCKDB_TYPE_BOOLEAN:
83
86
  return to_ruby_obj_boolean(result, col_idx, row_idx);
84
87
  case DUCKDB_TYPE_SMALLINT:
@@ -91,10 +94,8 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
91
94
  return to_ruby_obj_float(result, col_idx, row_idx);
92
95
  case DUCKDB_TYPE_DOUBLE:
93
96
  return to_ruby_obj_double(result, col_idx, row_idx);
94
- #ifdef HAVE_DUCKDB_VALUE_BLOB
95
97
  case DUCKDB_TYPE_BLOB:
96
98
  return to_ruby_obj_string_from_blob(result, col_idx, row_idx);
97
- #endif /* HAVE_DUCKDB_VALUE_BLOB */
98
99
  default:
99
100
  p = duckdb_value_varchar(result, col_idx, row_idx);
100
101
  if (p) {
@@ -104,7 +105,7 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
104
105
  #else
105
106
  free(p);
106
107
  #endif /* HAVE_DUCKDB_FREE */
107
- if (result->columns[col_idx].type == DUCKDB_TYPE_HUGEINT) {
108
+ if (duckdb_column_type(result, col_idx) == DUCKDB_TYPE_HUGEINT) {
108
109
  obj = rb_funcall(obj, rb_intern("to_i"), 0);
109
110
  }
110
111
  }
@@ -112,47 +113,75 @@ static VALUE to_ruby_obj(duckdb_result *result, idx_t col_idx, idx_t row_idx)
112
113
  return obj;
113
114
  }
114
115
 
115
- static VALUE row_array(rubyDuckDBResult *ctx, idx_t row_idx)
116
- {
116
+ static VALUE row_array(rubyDuckDBResult *ctx, idx_t row_idx) {
117
117
  idx_t col_idx;
118
- VALUE ary = rb_ary_new2(ctx->result.column_count);
119
- for(col_idx = 0; col_idx < ctx->result.column_count; col_idx++) {
118
+ idx_t column_count = duckdb_column_count(&(ctx->result));
119
+
120
+ VALUE ary = rb_ary_new2(column_count);
121
+ for(col_idx = 0; col_idx < column_count; col_idx++) {
120
122
  rb_ary_store(ary, col_idx, to_ruby_obj(&(ctx->result), col_idx, row_idx));
121
123
  }
122
124
  return ary;
123
125
  }
124
126
 
125
- static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj)
126
- {
127
+ static VALUE duckdb_result_row_size(VALUE oDuckDBResult, VALUE args, VALUE obj) {
127
128
  rubyDuckDBResult *ctx;
128
129
  Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
129
130
 
130
- return LONG2FIX(ctx->result.row_count);
131
+ return LONG2FIX(duckdb_row_count(&(ctx->result)));
131
132
  }
132
133
 
133
- static VALUE duckdb_result_each(VALUE oDuckDBResult)
134
- {
134
+ static VALUE duckdb_result_each(VALUE oDuckDBResult) {
135
135
  rubyDuckDBResult *ctx;
136
136
  idx_t row_idx = 0;
137
+ idx_t row_count = 0;
137
138
 
138
139
  RETURN_SIZED_ENUMERATOR(oDuckDBResult, 0, 0, duckdb_result_row_size);
139
140
 
140
141
  Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
141
- for (row_idx = 0; row_idx < ctx->result.row_count; row_idx++) {
142
+ row_count = duckdb_row_count(&(ctx->result));
143
+ for (row_idx = 0; row_idx < row_count; row_idx++) {
142
144
  rb_yield(row_array(ctx, row_idx));
143
145
  }
144
146
  return oDuckDBResult;
145
147
  }
146
148
 
147
- VALUE create_result(void)
148
- {
149
+ /*
150
+ * call-seq:
151
+ * result.rows_changed -> integer
152
+ *
153
+ * Returns the count of rows changed.
154
+ *
155
+ * DuckDB::Database.open do |db|
156
+ * db.connect do |con|
157
+ * r = con.query('CREATE TABLE t2 (id INT)')
158
+ * r.rows_changed # => 0
159
+ * r = con.query('INSERT INTO t2 VALUES (1), (2), (3)')
160
+ * r.rows_changed # => 3
161
+ * r = con.query('UPDATE t2 SET id = id + 1 WHERE id > 1')
162
+ * r.rows_changed # => 2
163
+ * r = con.query('DELETE FROM t2 WHERE id = 0')
164
+ * r.rows_changed # => 0
165
+ * r = con.query('DELETE FROM t2 WHERE id = 4')
166
+ * r.rows_changed # => 1
167
+ * end
168
+ * end
169
+ *
170
+ */
171
+ static VALUE duckdb_result_rows_changed(VALUE oDuckDBResult) {
172
+ rubyDuckDBResult *ctx;
173
+ Data_Get_Struct(oDuckDBResult, rubyDuckDBResult, ctx);
174
+ return LL2NUM(duckdb_rows_changed(&(ctx->result)));
175
+ }
176
+
177
+ VALUE create_result(void) {
149
178
  return allocate(cDuckDBResult);
150
179
  }
151
180
 
152
- void init_duckdb_result(void)
153
- {
181
+ void init_duckdb_result(void) {
154
182
  cDuckDBResult = rb_define_class_under(mDuckDB, "Result", rb_cObject);
155
183
  rb_define_alloc_func(cDuckDBResult, allocate);
156
184
 
157
185
  rb_define_method(cDuckDBResult, "each", duckdb_result_each, 0);
186
+ rb_define_method(cDuckDBResult, "rows_changed", duckdb_result_rows_changed, 0);
158
187
  }