duckdb 0.2.8.0 → 0.3.2.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.
@@ -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
  }