extralite 2.6 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.yardopts +1 -1
- data/CHANGELOG.md +32 -17
- data/Gemfile +4 -0
- data/Gemfile-bundle +1 -1
- data/README.md +262 -75
- data/Rakefile +18 -0
- data/TODO.md +0 -9
- data/examples/kv_store.rb +49 -0
- data/examples/multi_fiber.rb +16 -0
- data/examples/on_progress.rb +9 -0
- data/examples/pubsub_store_polyphony.rb +194 -0
- data/examples/pubsub_store_threads.rb +204 -0
- data/ext/extralite/changeset.c +3 -3
- data/ext/extralite/common.c +173 -87
- data/ext/extralite/database.c +650 -315
- data/ext/extralite/extconf.rb +7 -11
- data/ext/extralite/extralite.h +89 -48
- data/ext/extralite/iterator.c +6 -84
- data/ext/extralite/query.c +165 -256
- data/extralite-bundle.gemspec +1 -1
- data/extralite.gemspec +1 -1
- data/gemspec.rb +10 -11
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +27 -17
- data/lib/sequel/adapters/extralite.rb +1 -1
- data/test/helper.rb +2 -1
- data/test/perf_argv_transform.rb +74 -0
- data/test/perf_hash_transform.rb +66 -0
- data/test/perf_polyphony.rb +74 -0
- data/test/test_changeset.rb +2 -2
- data/test/test_database.rb +531 -115
- data/test/test_extralite.rb +2 -2
- data/test/test_iterator.rb +28 -13
- data/test/test_query.rb +348 -111
- data/test/test_sequel.rb +4 -4
- metadata +20 -14
- data/Gemfile.lock +0 -37
data/ext/extralite/query.c
CHANGED
@@ -14,6 +14,10 @@ VALUE cQuery;
|
|
14
14
|
ID ID_inspect;
|
15
15
|
ID ID_slice;
|
16
16
|
|
17
|
+
VALUE SYM_hash;
|
18
|
+
VALUE SYM_argv;
|
19
|
+
VALUE SYM_ary;
|
20
|
+
|
17
21
|
#define DB_GVL_MODE(query) Database_prepare_gvl_mode(query->db_struct)
|
18
22
|
|
19
23
|
static size_t Query_size(const void *ptr) {
|
@@ -24,12 +28,14 @@ static void Query_mark(void *ptr) {
|
|
24
28
|
Query_t *query = ptr;
|
25
29
|
rb_gc_mark_movable(query->db);
|
26
30
|
rb_gc_mark_movable(query->sql);
|
31
|
+
rb_gc_mark_movable(query->transform_proc);
|
27
32
|
}
|
28
33
|
|
29
34
|
static void Query_compact(void *ptr) {
|
30
35
|
Query_t *query = ptr;
|
31
36
|
query->db = rb_gc_location(query->db);
|
32
37
|
query->sql = rb_gc_location(query->sql);
|
38
|
+
query->transform_proc = rb_gc_location(query->transform_proc);
|
33
39
|
}
|
34
40
|
|
35
41
|
static void Query_free(void *ptr) {
|
@@ -48,6 +54,7 @@ static VALUE Query_allocate(VALUE klass) {
|
|
48
54
|
Query_t *query = ALLOC(Query_t);
|
49
55
|
query->db = Qnil;
|
50
56
|
query->sql = Qnil;
|
57
|
+
query->transform_proc = Qnil;
|
51
58
|
query->sqlite3_db = NULL;
|
52
59
|
query->stmt = NULL;
|
53
60
|
return TypedData_Wrap_Struct(klass, &Query_type, query);
|
@@ -59,6 +66,27 @@ static inline Query_t *self_to_query(VALUE obj) {
|
|
59
66
|
return query;
|
60
67
|
}
|
61
68
|
|
69
|
+
static inline enum query_mode symbol_to_query_mode(VALUE sym) {
|
70
|
+
if (sym == SYM_hash) return QUERY_HASH;
|
71
|
+
if (sym == SYM_argv) return QUERY_ARGV;
|
72
|
+
if (sym == SYM_ary) return QUERY_ARY;
|
73
|
+
|
74
|
+
rb_raise(cError, "Invalid query mode");
|
75
|
+
}
|
76
|
+
|
77
|
+
static inline VALUE query_mode_to_symbol(enum query_mode query_mode) {
|
78
|
+
switch (query_mode) {
|
79
|
+
case QUERY_HASH:
|
80
|
+
return SYM_hash;
|
81
|
+
case QUERY_ARGV:
|
82
|
+
return SYM_argv;
|
83
|
+
case QUERY_ARY:
|
84
|
+
return SYM_ary;
|
85
|
+
default:
|
86
|
+
rb_raise(cError, "Invalid mode");
|
87
|
+
}
|
88
|
+
}
|
89
|
+
|
62
90
|
/* Initializes a new prepared query with the given database and SQL string. A
|
63
91
|
* `Query` is normally instantiated by calling `Database#prepare`:
|
64
92
|
*
|
@@ -66,9 +94,10 @@ static inline Query_t *self_to_query(VALUE obj) {
|
|
66
94
|
*
|
67
95
|
* @param db [Extralite::Database] associated database
|
68
96
|
* @param sql [String] SQL string
|
97
|
+
* @param mode [Symbol] query mode
|
69
98
|
* @return [void]
|
70
99
|
*/
|
71
|
-
VALUE Query_initialize(VALUE self, VALUE db, VALUE sql) {
|
100
|
+
VALUE Query_initialize(VALUE self, VALUE db, VALUE sql, VALUE mode) {
|
72
101
|
Query_t *query = self_to_query(self);
|
73
102
|
|
74
103
|
sql = rb_funcall(sql, ID_strip, 0);
|
@@ -77,6 +106,8 @@ VALUE Query_initialize(VALUE self, VALUE db, VALUE sql) {
|
|
77
106
|
|
78
107
|
RB_OBJ_WRITE(self, &query->db, db);
|
79
108
|
RB_OBJ_WRITE(self, &query->sql, sql);
|
109
|
+
if (rb_block_given_p())
|
110
|
+
RB_OBJ_WRITE(self, &query->transform_proc, rb_block_proc());
|
80
111
|
|
81
112
|
query->db = db;
|
82
113
|
query->db_struct = self_to_database(db);
|
@@ -84,6 +115,7 @@ VALUE Query_initialize(VALUE self, VALUE db, VALUE sql) {
|
|
84
115
|
query->stmt = NULL;
|
85
116
|
query->closed = 0;
|
86
117
|
query->eof = 0;
|
118
|
+
query->query_mode = symbol_to_query_mode(mode);
|
87
119
|
|
88
120
|
return Qnil;
|
89
121
|
}
|
@@ -91,7 +123,7 @@ VALUE Query_initialize(VALUE self, VALUE db, VALUE sql) {
|
|
91
123
|
static inline void query_reset(Query_t *query) {
|
92
124
|
if (!query->stmt)
|
93
125
|
prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
|
94
|
-
|
126
|
+
Database_issue_query(query->db_struct, query->sql);
|
95
127
|
sqlite3_reset(query->stmt);
|
96
128
|
query->eof = 0;
|
97
129
|
}
|
@@ -99,9 +131,7 @@ static inline void query_reset(Query_t *query) {
|
|
99
131
|
static inline void query_reset_and_bind(Query_t *query, int argc, VALUE * argv) {
|
100
132
|
if (!query->stmt)
|
101
133
|
prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
|
102
|
-
|
103
|
-
TRACE_SQL(query->db_struct, query->sql);
|
104
|
-
|
134
|
+
Database_issue_query(query->db_struct, query->sql);
|
105
135
|
sqlite3_reset(query->stmt);
|
106
136
|
query->eof = 0;
|
107
137
|
if (argc > 0) {
|
@@ -128,8 +158,6 @@ VALUE Query_reset(VALUE self) {
|
|
128
158
|
if (query->closed) rb_raise(cError, "Query is closed");
|
129
159
|
|
130
160
|
query_reset(query);
|
131
|
-
TRACE_SQL(query->db_struct, query->sql);
|
132
|
-
|
133
161
|
return self;
|
134
162
|
}
|
135
163
|
|
@@ -175,7 +203,7 @@ VALUE Query_eof_p(VALUE self) {
|
|
175
203
|
|
176
204
|
#define MAX_ROWS(max_rows) (max_rows == SINGLE_ROW ? 1 : max_rows)
|
177
205
|
|
178
|
-
static inline VALUE Query_perform_next(VALUE self, int max_rows,
|
206
|
+
static inline VALUE Query_perform_next(VALUE self, int max_rows, safe_query_impl call) {
|
179
207
|
Query_t *query = self_to_query(self);
|
180
208
|
if (query->closed) rb_raise(cError, "Query is closed");
|
181
209
|
|
@@ -184,69 +212,37 @@ static inline VALUE Query_perform_next(VALUE self, int max_rows, VALUE (*call)(q
|
|
184
212
|
|
185
213
|
query_ctx ctx = QUERY_CTX(
|
186
214
|
self,
|
215
|
+
query->sql,
|
187
216
|
query->db_struct,
|
188
217
|
query->stmt,
|
189
218
|
Qnil,
|
190
|
-
|
219
|
+
query->transform_proc,
|
220
|
+
query->query_mode,
|
221
|
+
ROW_YIELD_OR_MODE(max_rows == SINGLE_ROW ? ROW_SINGLE : ROW_MULTI),
|
191
222
|
MAX_ROWS(max_rows)
|
192
223
|
);
|
193
224
|
VALUE result = call(&ctx);
|
194
225
|
query->eof = ctx.eof;
|
195
|
-
return (ctx.
|
226
|
+
return (ctx.row_mode == ROW_YIELD) ? self : result;
|
196
227
|
}
|
197
228
|
|
198
229
|
#define MAX_ROWS_FROM_ARGV(argc, argv) (argc == 1 ? FIX2INT(argv[0]) : SINGLE_ROW)
|
199
230
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
* @return [Hash, Extralite::Query] next row or self if block is given
|
212
|
-
* @overload next_hash()
|
213
|
-
* @return [Hash, Extralite::Query] next row or self if block is given
|
214
|
-
* @overload next(row_count)
|
215
|
-
* @param row_count [Integer] maximum row count or -1 for all rows
|
216
|
-
* @return [Array<Hash>, Extralite::Query] next rows or self if block is given
|
217
|
-
* @overload next_hash(row_count)
|
218
|
-
* @param row_count [Integer] maximum row count or -1 for all rows
|
219
|
-
* @return [Array<Hash>, Extralite::Query] next rows or self if block is given
|
220
|
-
*/
|
221
|
-
VALUE Query_next_hash(int argc, VALUE *argv, VALUE self) {
|
222
|
-
rb_check_arity(argc, 0, 1);
|
223
|
-
return Query_perform_next(self, MAX_ROWS_FROM_ARGV(argc, argv), safe_query_hash);
|
224
|
-
}
|
225
|
-
|
226
|
-
/* Returns the next 1 or more rows from the associated query's result set as an
|
227
|
-
* array.
|
228
|
-
*
|
229
|
-
* If no row count is given, a single row is returned. If a row count is given,
|
230
|
-
* an array containing up to the `row_count` rows is returned. If `row_count` is
|
231
|
-
* -1, all rows are returned. If the end of the result set has been reached,
|
232
|
-
* `nil` is returned.
|
233
|
-
*
|
234
|
-
* If a block is given, rows are passed to the block and self is returned.
|
235
|
-
*
|
236
|
-
* @overload next_ary()
|
237
|
-
* @return [Array, Extralite::Query] next row or self if block is given
|
238
|
-
* @overload next_ary(row_count)
|
239
|
-
* @param row_count [Integer] maximum row count or -1 for all rows
|
240
|
-
* @return [Array<Array>, Extralite::Query] next rows or self if block is given
|
241
|
-
*/
|
242
|
-
VALUE Query_next_ary(int argc, VALUE *argv, VALUE self) {
|
243
|
-
rb_check_arity(argc, 0, 1);
|
244
|
-
return Query_perform_next(self, MAX_ROWS_FROM_ARGV(argc, argv), safe_query_ary);
|
231
|
+
inline safe_query_impl query_impl(enum query_mode query_mode) {
|
232
|
+
switch (query_mode) {
|
233
|
+
case QUERY_HASH:
|
234
|
+
return safe_query_hash;
|
235
|
+
case QUERY_ARGV:
|
236
|
+
return safe_query_argv;
|
237
|
+
case QUERY_ARY:
|
238
|
+
return safe_query_ary;
|
239
|
+
default:
|
240
|
+
rb_raise(cError, "Invalid query mode (query_impl)");
|
241
|
+
}
|
245
242
|
}
|
246
243
|
|
247
|
-
/* Returns the next 1 or more rows from the associated query's result set
|
248
|
-
*
|
249
|
-
* raised.
|
244
|
+
/* Returns the next 1 or more rows from the associated query's result set. The
|
245
|
+
* row value is returned according to the query mode and the query transform.
|
250
246
|
*
|
251
247
|
* If no row count is given, a single row is returned. If a row count is given,
|
252
248
|
* an array containing up to the `row_count` rows is returned. If `row_count` is
|
@@ -255,92 +251,41 @@ VALUE Query_next_ary(int argc, VALUE *argv, VALUE self) {
|
|
255
251
|
*
|
256
252
|
* If a block is given, rows are passed to the block and self is returned.
|
257
253
|
*
|
258
|
-
* @overload
|
259
|
-
* @return [
|
260
|
-
* @overload
|
254
|
+
* @overload next()
|
255
|
+
* @return [any, Extralite::Query] next row or self if block is given
|
256
|
+
* @overload next(row_count)
|
261
257
|
* @param row_count [Integer] maximum row count or -1 for all rows
|
262
|
-
* @return [Array<
|
258
|
+
* @return [Array<any>, Extralite::Query] next rows or self if block is given
|
263
259
|
*/
|
264
|
-
VALUE
|
265
|
-
rb_check_arity(argc, 0, 1);
|
266
|
-
return Query_perform_next(self, MAX_ROWS_FROM_ARGV(argc, argv), safe_query_single_column);
|
267
|
-
}
|
268
|
-
|
269
|
-
/* Returns all rows in the associated query's result set as hashes.
|
270
|
-
*
|
271
|
-
* @overload to_a()
|
272
|
-
* @return [Array<Hash>] all rows
|
273
|
-
* @overload to_a_hash
|
274
|
-
* @return [Array<Hash>] all rows
|
275
|
-
*/
|
276
|
-
VALUE Query_to_a_hash(VALUE self) {
|
277
|
-
Query_t *query = self_to_query(self);
|
278
|
-
query_reset(query);
|
279
|
-
return Query_perform_next(self, ALL_ROWS, safe_query_hash);
|
280
|
-
}
|
281
|
-
|
282
|
-
/* Returns all rows in the associated query's result set as arrays.
|
283
|
-
*
|
284
|
-
* @return [Array<Array>] all rows
|
285
|
-
*/
|
286
|
-
VALUE Query_to_a_ary(VALUE self) {
|
287
|
-
Query_t *query = self_to_query(self);
|
288
|
-
query_reset(query);
|
289
|
-
return Query_perform_next(self, ALL_ROWS, safe_query_ary);
|
290
|
-
}
|
291
|
-
|
292
|
-
/* Returns all rows in the associated query's result set as single values. If
|
293
|
-
* the result set contains more than one column an error is raised.
|
294
|
-
*
|
295
|
-
* @return [Array<Object>] all rows
|
296
|
-
*/
|
297
|
-
VALUE Query_to_a_single_column(VALUE self) {
|
260
|
+
VALUE Query_next(int argc, VALUE *argv, VALUE self) {
|
298
261
|
Query_t *query = self_to_query(self);
|
299
|
-
|
300
|
-
return Query_perform_next(self,
|
301
|
-
}
|
302
|
-
|
303
|
-
/* Iterates through the result set, passing each row to the given block as a
|
304
|
-
* hash. If no block is given, returns a `Extralite::Iterator` instance in hash
|
305
|
-
* mode.
|
306
|
-
*
|
307
|
-
* @return [Extralite::Query, Extralite::Iterator] self or an iterator if no block is given
|
308
|
-
*/
|
309
|
-
VALUE Query_each_hash(VALUE self) {
|
310
|
-
if (!rb_block_given_p()) return rb_funcall(cIterator, ID_new, 2, self, SYM_hash);
|
311
|
-
|
312
|
-
Query_t *query = self_to_query(self);
|
313
|
-
query_reset(query);
|
314
|
-
return Query_perform_next(self, ALL_ROWS, safe_query_hash);
|
262
|
+
rb_check_arity(argc, 0, 1);
|
263
|
+
return Query_perform_next(self, MAX_ROWS_FROM_ARGV(argc, argv), query_impl(query->query_mode));
|
315
264
|
}
|
316
265
|
|
317
|
-
/*
|
318
|
-
*
|
319
|
-
* array mode.
|
266
|
+
/* Returns all rows in the associated query's result set. Rows are returned
|
267
|
+
* according to the query mode and the query transform.
|
320
268
|
*
|
321
|
-
* @return [
|
269
|
+
* @return [Array<any>] all rows
|
322
270
|
*/
|
323
|
-
VALUE
|
324
|
-
if (!rb_block_given_p()) return rb_funcall(cIterator, ID_new, 2, self, SYM_ary);
|
325
|
-
|
271
|
+
VALUE Query_to_a(VALUE self) {
|
326
272
|
Query_t *query = self_to_query(self);
|
327
273
|
query_reset(query);
|
328
|
-
return Query_perform_next(self, ALL_ROWS,
|
274
|
+
return Query_perform_next(self, ALL_ROWS, query_impl(query->query_mode));
|
329
275
|
}
|
330
276
|
|
331
|
-
/* Iterates through the result set, passing each row to the given block
|
332
|
-
*
|
333
|
-
*
|
334
|
-
* single column mode.
|
277
|
+
/* Iterates through the result set, passing each row to the given block. If no
|
278
|
+
* block is given, returns a `Extralite::Iterator` instance. Rows are given to
|
279
|
+
* the block according to the query mode and the query transform.
|
335
280
|
*
|
336
281
|
* @return [Extralite::Query, Extralite::Iterator] self or an iterator if no block is given
|
337
282
|
*/
|
338
|
-
VALUE
|
339
|
-
if (!rb_block_given_p()) return rb_funcall(cIterator, ID_new,
|
283
|
+
VALUE Query_each(VALUE self) {
|
284
|
+
if (!rb_block_given_p()) return rb_funcall(cIterator, ID_new, 1, self);
|
340
285
|
|
341
286
|
Query_t *query = self_to_query(self);
|
342
287
|
query_reset(query);
|
343
|
-
return Query_perform_next(self, ALL_ROWS,
|
288
|
+
return Query_perform_next(self, ALL_ROWS, query_impl(query->query_mode));
|
344
289
|
}
|
345
290
|
|
346
291
|
/* call-seq:
|
@@ -440,10 +385,13 @@ VALUE Query_batch_execute(VALUE self, VALUE parameters) {
|
|
440
385
|
|
441
386
|
query_ctx ctx = QUERY_CTX(
|
442
387
|
self,
|
388
|
+
query->sql,
|
443
389
|
query->db_struct,
|
444
390
|
query->stmt,
|
445
391
|
parameters,
|
446
|
-
|
392
|
+
Qnil,
|
393
|
+
QUERY_HASH,
|
394
|
+
ROW_YIELD_OR_MODE(ROW_MULTI),
|
447
395
|
ALL_ROWS
|
448
396
|
);
|
449
397
|
return safe_batch_execute(&ctx);
|
@@ -462,6 +410,8 @@ VALUE Query_batch_execute(VALUE self, VALUE parameters) {
|
|
462
410
|
* invocation of the query, and the total number of changes is returned.
|
463
411
|
* Otherwise, an array containing the resulting rows for each invocation is
|
464
412
|
* returned.
|
413
|
+
*
|
414
|
+
* Rows are returned according to the query mode and transform.
|
465
415
|
*
|
466
416
|
* q = db.prepare('insert into foo values (?, ?) returning bar, baz')
|
467
417
|
* records = [
|
@@ -473,7 +423,7 @@ VALUE Query_batch_execute(VALUE self, VALUE parameters) {
|
|
473
423
|
* *
|
474
424
|
* @param sql [String] query SQL
|
475
425
|
* @param parameters [Array<Array, Hash>, Enumerable, Enumerator, Callable] parameters to run query with
|
476
|
-
* @return [Array<
|
426
|
+
* @return [Array<Array>, Integer] Returned rows or total number of changes effected
|
477
427
|
*/
|
478
428
|
VALUE Query_batch_query(VALUE self, VALUE parameters) {
|
479
429
|
Query_t *query = self_to_query(self);
|
@@ -484,103 +434,18 @@ VALUE Query_batch_query(VALUE self, VALUE parameters) {
|
|
484
434
|
|
485
435
|
query_ctx ctx = QUERY_CTX(
|
486
436
|
self,
|
437
|
+
query->sql,
|
487
438
|
query->db_struct,
|
488
439
|
query->stmt,
|
489
440
|
parameters,
|
490
|
-
|
441
|
+
query->transform_proc,
|
442
|
+
query->query_mode,
|
443
|
+
ROW_YIELD_OR_MODE(ROW_MULTI),
|
491
444
|
ALL_ROWS
|
492
445
|
);
|
493
446
|
return safe_batch_query(&ctx);
|
494
447
|
}
|
495
448
|
|
496
|
-
/* call-seq:
|
497
|
-
* query.batch_query_ary(sql, params_array) -> rows
|
498
|
-
* query.batch_query_ary(sql, enumerable) -> rows
|
499
|
-
* query.batch_query_ary(sql, callable) -> rows
|
500
|
-
* query.batch_query_ary(sql, params_array) { |rows| ... } -> changes
|
501
|
-
* query.batch_query_ary(sql, enumerable) { |rows| ... } -> changes
|
502
|
-
* query.batch_query_ary(sql, callable) { |rows| ... } -> changes
|
503
|
-
*
|
504
|
-
* Executes the prepared query for each list of parameters in the given paramter
|
505
|
-
* source. If a block is given, it is called with the resulting rows for each
|
506
|
-
* invocation of the query, and the total number of changes is returned.
|
507
|
-
* Otherwise, an array containing the resulting rows for each invocation is
|
508
|
-
* returned. Rows are represented as arrays.
|
509
|
-
*
|
510
|
-
* q = db.prepare('insert into foo values (?, ?) returning bar, baz')
|
511
|
-
* records = [
|
512
|
-
* [1, 2],
|
513
|
-
* [3, 4]
|
514
|
-
* ]
|
515
|
-
* q.batch_query_ary(records)
|
516
|
-
* #=> [{ bar: 1, baz: 2 }, { bar: 3, baz: 4}]
|
517
|
-
* *
|
518
|
-
* @param sql [String] query SQL
|
519
|
-
* @param parameters [Array<Array, Hash>, Enumerable, Enumerator, Callable] parameters to run query with
|
520
|
-
* @return [Array<Hash>, Integer] Total number of changes effected
|
521
|
-
*/
|
522
|
-
VALUE Query_batch_query_ary(VALUE self, VALUE parameters) {
|
523
|
-
Query_t *query = self_to_query(self);
|
524
|
-
if (query->closed) rb_raise(cError, "Query is closed");
|
525
|
-
|
526
|
-
if (!query->stmt)
|
527
|
-
prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
|
528
|
-
|
529
|
-
query_ctx ctx = QUERY_CTX(
|
530
|
-
self,
|
531
|
-
query->db_struct,
|
532
|
-
query->stmt,
|
533
|
-
parameters,
|
534
|
-
QUERY_MODE(QUERY_MULTI_ROW),
|
535
|
-
ALL_ROWS
|
536
|
-
);
|
537
|
-
return safe_batch_query_ary(&ctx);
|
538
|
-
}
|
539
|
-
|
540
|
-
/* call-seq:
|
541
|
-
* query.batch_query_single_column(sql, params_array) -> rows
|
542
|
-
* query.batch_query_single_column(sql, enumerable) -> rows
|
543
|
-
* query.batch_query_single_column(sql, callable) -> rows
|
544
|
-
* query.batch_query_single_column(sql, params_array) { |rows| ... } -> changes
|
545
|
-
* query.batch_query_single_column(sql, enumerable) { |rows| ... } -> changes
|
546
|
-
* query.batch_query_single_column(sql, callable) { |rows| ... } -> changes
|
547
|
-
*
|
548
|
-
* Executes the prepared query for each list of parameters in the given paramter
|
549
|
-
* source. If a block is given, it is called with the resulting rows for each
|
550
|
-
* invocation of the query, and the total number of changes is returned.
|
551
|
-
* Otherwise, an array containing the resulting rows for each invocation is
|
552
|
-
* returned. Rows are represented as single values.
|
553
|
-
*
|
554
|
-
* q = db.prepare('insert into foo values (?, ?) returning bar, baz')
|
555
|
-
* records = [
|
556
|
-
* [1, 2],
|
557
|
-
* [3, 4]
|
558
|
-
* ]
|
559
|
-
* q.batch_query_single_column(records)
|
560
|
-
* #=> [{ bar: 1, baz: 2 }, { bar: 3, baz: 4}]
|
561
|
-
* *
|
562
|
-
* @param sql [String] query SQL
|
563
|
-
* @param parameters [Array<Array, Hash>, Enumerable, Enumerator, Callable] parameters to run query with
|
564
|
-
* @return [Array<Hash>, Integer] Total number of changes effected
|
565
|
-
*/
|
566
|
-
VALUE Query_batch_query_single_column(VALUE self, VALUE parameters) {
|
567
|
-
Query_t *query = self_to_query(self);
|
568
|
-
if (query->closed) rb_raise(cError, "Query is closed");
|
569
|
-
|
570
|
-
if (!query->stmt)
|
571
|
-
prepare_single_stmt(DB_GVL_MODE(query), query->sqlite3_db, &query->stmt, query->sql);
|
572
|
-
|
573
|
-
query_ctx ctx = QUERY_CTX(
|
574
|
-
self,
|
575
|
-
query->db_struct,
|
576
|
-
query->stmt,
|
577
|
-
parameters,
|
578
|
-
QUERY_MODE(QUERY_MULTI_ROW),
|
579
|
-
ALL_ROWS
|
580
|
-
);
|
581
|
-
return safe_batch_query_single_column(&ctx);
|
582
|
-
}
|
583
|
-
|
584
449
|
/* Returns the database associated with the query.
|
585
450
|
*
|
586
451
|
* @overload database()
|
@@ -622,7 +487,12 @@ VALUE Query_columns(VALUE self) {
|
|
622
487
|
*/
|
623
488
|
VALUE Query_clone(VALUE self) {
|
624
489
|
Query_t *query = self_to_query(self);
|
625
|
-
|
490
|
+
VALUE args[] = {
|
491
|
+
query->db,
|
492
|
+
query->sql,
|
493
|
+
query_mode_to_symbol(query->query_mode)
|
494
|
+
};
|
495
|
+
return rb_funcall_with_block(cQuery, ID_new, 3, args, query->transform_proc);
|
626
496
|
}
|
627
497
|
|
628
498
|
/* Closes the query. Attempting to run a closed query will raise an error.
|
@@ -675,6 +545,27 @@ VALUE Query_status(int argc, VALUE* argv, VALUE self) {
|
|
675
545
|
return INT2NUM(value);
|
676
546
|
}
|
677
547
|
|
548
|
+
/* Sets the transform block to the given block. If a transform block is set,
|
549
|
+
* calls to #to_a, #next, #each and #batch_query will transform values fetched
|
550
|
+
* from the database using the transform block before passing them to the
|
551
|
+
* application code. To remove the transform block, call `#transform`
|
552
|
+
* without a block. The transform for each row is done by passing the row hash
|
553
|
+
* to the block.
|
554
|
+
*
|
555
|
+
* # fetch column c as an ORM object
|
556
|
+
* q = db.prepare('select * from foo order by a').transform do |h|
|
557
|
+
* MyModel.new(h)
|
558
|
+
* end
|
559
|
+
*
|
560
|
+
* @return [Extralite::Query] query
|
561
|
+
*/
|
562
|
+
VALUE Query_transform(VALUE self) {
|
563
|
+
Query_t *query = self_to_query(self);
|
564
|
+
|
565
|
+
RB_OBJ_WRITE(self, &query->transform_proc, rb_block_given_p() ? rb_block_proc() : Qnil);
|
566
|
+
return self;
|
567
|
+
}
|
568
|
+
|
678
569
|
/* Returns a short string representation of the query instance, including the
|
679
570
|
* SQL string.
|
680
571
|
*
|
@@ -693,50 +584,68 @@ VALUE Query_inspect(VALUE self) {
|
|
693
584
|
return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, sql);
|
694
585
|
}
|
695
586
|
|
587
|
+
/* Returns the query mode.
|
588
|
+
*
|
589
|
+
* @return [Symbol] query mode
|
590
|
+
*/
|
591
|
+
VALUE Query_mode_get(VALUE self) {
|
592
|
+
Query_t *query = self_to_query(self);
|
593
|
+
return query_mode_to_symbol(query->query_mode);
|
594
|
+
}
|
595
|
+
|
596
|
+
/* call-seq:
|
597
|
+
* query.mode = mode
|
598
|
+
*
|
599
|
+
* Sets the query mode. This can be one of `:hash`, `:argv`, `:ary`.
|
600
|
+
*
|
601
|
+
* @param mode [Symbol] query mode
|
602
|
+
* @return [Symbol] query mode
|
603
|
+
*/
|
604
|
+
VALUE Query_mode_set(VALUE self, VALUE mode) {
|
605
|
+
Query_t *query = self_to_query(self);
|
606
|
+
query->query_mode = symbol_to_query_mode(mode);
|
607
|
+
return mode;
|
608
|
+
}
|
609
|
+
|
696
610
|
void Init_ExtraliteQuery(void) {
|
697
611
|
VALUE mExtralite = rb_define_module("Extralite");
|
698
612
|
|
699
613
|
cQuery = rb_define_class_under(mExtralite, "Query", rb_cObject);
|
700
614
|
rb_define_alloc_func(cQuery, Query_allocate);
|
701
615
|
|
702
|
-
rb_define_method(cQuery, "bind",
|
703
|
-
rb_define_method(cQuery, "close",
|
704
|
-
rb_define_method(cQuery, "closed?",
|
705
|
-
rb_define_method(cQuery, "columns",
|
706
|
-
rb_define_method(cQuery, "clone",
|
707
|
-
rb_define_method(cQuery, "database",
|
708
|
-
rb_define_method(cQuery, "db",
|
709
|
-
rb_define_method(cQuery, "dup",
|
710
|
-
|
711
|
-
rb_define_method(cQuery, "
|
712
|
-
rb_define_method(cQuery, "
|
713
|
-
rb_define_method(cQuery, "
|
714
|
-
rb_define_method(cQuery, "
|
715
|
-
|
716
|
-
rb_define_method(cQuery, "
|
717
|
-
rb_define_method(cQuery, "
|
718
|
-
rb_define_method(cQuery, "
|
719
|
-
rb_define_method(cQuery, "
|
720
|
-
rb_define_method(cQuery, "
|
721
|
-
rb_define_method(cQuery, "
|
722
|
-
rb_define_method(cQuery, "
|
723
|
-
rb_define_method(cQuery, "
|
724
|
-
rb_define_method(cQuery, "
|
725
|
-
|
726
|
-
rb_define_method(cQuery, "next", Query_next_hash, -1);
|
727
|
-
rb_define_method(cQuery, "next_ary", Query_next_ary, -1);
|
728
|
-
rb_define_method(cQuery, "next_hash", Query_next_hash, -1);
|
729
|
-
rb_define_method(cQuery, "next_single_column", Query_next_single_column, -1);
|
730
|
-
|
731
|
-
rb_define_method(cQuery, "reset", Query_reset, 0);
|
732
|
-
rb_define_method(cQuery, "sql", Query_sql, 0);
|
733
|
-
rb_define_method(cQuery, "status", Query_status, -1);
|
734
|
-
|
735
|
-
rb_define_method(cQuery, "to_a", Query_to_a_hash, 0);
|
736
|
-
rb_define_method(cQuery, "to_a_ary", Query_to_a_ary, 0);
|
737
|
-
rb_define_method(cQuery, "to_a_hash", Query_to_a_hash, 0);
|
738
|
-
rb_define_method(cQuery, "to_a_single_column", Query_to_a_single_column, 0);
|
616
|
+
rb_define_method(cQuery, "bind", Query_bind, -1);
|
617
|
+
rb_define_method(cQuery, "close", Query_close, 0);
|
618
|
+
rb_define_method(cQuery, "closed?", Query_closed_p, 0);
|
619
|
+
rb_define_method(cQuery, "columns", Query_columns, 0);
|
620
|
+
rb_define_method(cQuery, "clone", Query_clone, 0);
|
621
|
+
rb_define_method(cQuery, "database", Query_database, 0);
|
622
|
+
rb_define_method(cQuery, "db", Query_database, 0);
|
623
|
+
rb_define_method(cQuery, "dup", Query_clone, 0);
|
624
|
+
rb_define_method(cQuery, "each", Query_each, 0);
|
625
|
+
rb_define_method(cQuery, "eof?", Query_eof_p, 0);
|
626
|
+
rb_define_method(cQuery, "execute", Query_execute, -1);
|
627
|
+
rb_define_method(cQuery, "<<", Query_execute_chevrons, 1);
|
628
|
+
rb_define_method(cQuery, "batch_execute", Query_batch_execute, 1);
|
629
|
+
rb_define_method(cQuery, "batch_query", Query_batch_query, 1);
|
630
|
+
rb_define_method(cQuery, "initialize", Query_initialize, 3);
|
631
|
+
rb_define_method(cQuery, "inspect", Query_inspect, 0);
|
632
|
+
rb_define_method(cQuery, "mode", Query_mode_get, 0);
|
633
|
+
rb_define_method(cQuery, "mode=", Query_mode_set, 1);
|
634
|
+
rb_define_method(cQuery, "next", Query_next, -1);
|
635
|
+
rb_define_method(cQuery, "reset", Query_reset, 0);
|
636
|
+
rb_define_method(cQuery, "sql", Query_sql, 0);
|
637
|
+
rb_define_method(cQuery, "status", Query_status, -1);
|
638
|
+
rb_define_method(cQuery, "to_a", Query_to_a, 0);
|
639
|
+
rb_define_method(cQuery, "transform", Query_transform, 0);
|
739
640
|
|
740
641
|
ID_inspect = rb_intern("inspect");
|
741
642
|
ID_slice = rb_intern("slice");
|
643
|
+
|
644
|
+
SYM_hash = ID2SYM(rb_intern("hash"));
|
645
|
+
SYM_argv = ID2SYM(rb_intern("argv"));
|
646
|
+
SYM_ary = ID2SYM(rb_intern("ary"));
|
647
|
+
|
648
|
+
rb_gc_register_mark_object(SYM_hash);
|
649
|
+
rb_gc_register_mark_object(SYM_argv);
|
650
|
+
rb_gc_register_mark_object(SYM_ary);
|
742
651
|
}
|
data/extralite-bundle.gemspec
CHANGED
data/extralite.gemspec
CHANGED
data/gemspec.rb
CHANGED
@@ -8,19 +8,18 @@ def common_spec(s)
|
|
8
8
|
s.files = `git ls-files`.split
|
9
9
|
s.homepage = 'https://github.com/digital-fabric/extralite'
|
10
10
|
s.metadata = {
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
"changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
|
11
|
+
'homepage_uri' => 'https://github.com/digital-fabric/extralite',
|
12
|
+
'documentation_uri' => 'https://www.rubydoc.info/gems/extralite',
|
13
|
+
'changelog_uri' => 'https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md'
|
15
14
|
}
|
16
|
-
s.rdoc_options = [
|
17
|
-
s.extra_rdoc_files = [
|
18
|
-
s.require_paths = [
|
15
|
+
s.rdoc_options = ['--title', 'Extralite', '--main', 'README.md']
|
16
|
+
s.extra_rdoc_files = ['README.md']
|
17
|
+
s.require_paths = ['lib']
|
19
18
|
s.required_ruby_version = '>= 3.0'
|
20
19
|
|
21
|
-
s.add_development_dependency 'rake-compiler', '1.
|
22
|
-
s.add_development_dependency 'minitest', '5.
|
20
|
+
s.add_development_dependency 'rake-compiler', '1.2.7'
|
21
|
+
s.add_development_dependency 'minitest', '5.21.2'
|
23
22
|
s.add_development_dependency 'simplecov', '0.17.1'
|
24
|
-
s.add_development_dependency 'yard', '0.9.
|
25
|
-
s.add_development_dependency 'sequel', '5.
|
23
|
+
s.add_development_dependency 'yard', '0.9.34'
|
24
|
+
s.add_development_dependency 'sequel', '5.77.0'
|
26
25
|
end
|
data/lib/extralite/version.rb
CHANGED