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/database.c
CHANGED
@@ -16,14 +16,28 @@ ID ID_call;
|
|
16
16
|
ID ID_each;
|
17
17
|
ID ID_keys;
|
18
18
|
ID ID_new;
|
19
|
+
ID ID_pragma;
|
19
20
|
ID ID_strip;
|
20
21
|
ID ID_to_s;
|
21
22
|
ID ID_track;
|
22
23
|
|
24
|
+
VALUE SYM_at_least_once;
|
23
25
|
VALUE SYM_gvl_release_threshold;
|
26
|
+
VALUE SYM_once;
|
27
|
+
VALUE SYM_none;
|
28
|
+
VALUE SYM_normal;
|
29
|
+
VALUE SYM_pragma;
|
24
30
|
VALUE SYM_read_only;
|
25
|
-
VALUE
|
26
|
-
|
31
|
+
VALUE SYM_wal;
|
32
|
+
|
33
|
+
struct progress_handler global_progress_handler = {
|
34
|
+
.mode = PROGRESS_NONE,
|
35
|
+
.proc = Qnil,
|
36
|
+
.period = DEFAULT_PROGRESS_HANDLER_PERIOD,
|
37
|
+
.tick = DEFAULT_PROGRESS_HANDLER_TICK,
|
38
|
+
.tick_count = 0,
|
39
|
+
.call_count = 0
|
40
|
+
};
|
27
41
|
|
28
42
|
#define DB_GVL_MODE(db) Database_prepare_gvl_mode(db)
|
29
43
|
|
@@ -34,13 +48,13 @@ static size_t Database_size(const void *ptr) {
|
|
34
48
|
static void Database_mark(void *ptr) {
|
35
49
|
Database_t *db = ptr;
|
36
50
|
rb_gc_mark_movable(db->trace_proc);
|
37
|
-
rb_gc_mark_movable(db->
|
51
|
+
rb_gc_mark_movable(db->progress_handler.proc);
|
38
52
|
}
|
39
53
|
|
40
54
|
static void Database_compact(void *ptr) {
|
41
55
|
Database_t *db = ptr;
|
42
|
-
db->trace_proc
|
43
|
-
db->
|
56
|
+
db->trace_proc = rb_gc_location(db->trace_proc);
|
57
|
+
db->progress_handler.proc = rb_gc_location(db->progress_handler.proc);
|
44
58
|
}
|
45
59
|
|
46
60
|
static void Database_free(void *ptr) {
|
@@ -57,7 +71,10 @@ static const rb_data_type_t Database_type = {
|
|
57
71
|
|
58
72
|
static VALUE Database_allocate(VALUE klass) {
|
59
73
|
Database_t *db = ALLOC(Database_t);
|
60
|
-
db->sqlite3_db =
|
74
|
+
db->sqlite3_db = NULL;
|
75
|
+
db->trace_proc = Qnil;
|
76
|
+
db->progress_handler.proc = Qnil;
|
77
|
+
db->progress_handler.mode = PROGRESS_NONE;
|
61
78
|
return TypedData_Wrap_Struct(klass, &Database_type, db);
|
62
79
|
}
|
63
80
|
|
@@ -78,12 +95,10 @@ inline sqlite3 *Database_sqlite3_db(VALUE self) {
|
|
78
95
|
return self_to_database(self)->sqlite3_db;
|
79
96
|
}
|
80
97
|
|
81
|
-
/*
|
82
|
-
* Extralite.sqlite3_version -> version
|
98
|
+
/* Returns the sqlite3 library version used by Extralite.
|
83
99
|
*
|
84
|
-
*
|
100
|
+
* @return [String] SQLite version
|
85
101
|
*/
|
86
|
-
|
87
102
|
VALUE Extralite_sqlite3_version(VALUE self) {
|
88
103
|
return rb_str_new_cstr(sqlite3_version);
|
89
104
|
}
|
@@ -100,40 +115,64 @@ default_flags:
|
|
100
115
|
return SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE;
|
101
116
|
}
|
102
117
|
|
103
|
-
VALUE Database_execute(int argc, VALUE *argv, VALUE self);
|
104
|
-
|
105
118
|
void Database_apply_opts(VALUE self, Database_t *db, VALUE opts) {
|
106
119
|
VALUE value = Qnil;
|
107
120
|
|
121
|
+
// :gvl_release_threshold
|
108
122
|
value = rb_hash_aref(opts, SYM_gvl_release_threshold);
|
109
123
|
if (!NIL_P(value)) db->gvl_release_threshold = NUM2INT(value);
|
110
124
|
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
Database_execute(1, &value, self);
|
115
|
-
}
|
125
|
+
// :pragma
|
126
|
+
value = rb_hash_aref(opts, SYM_pragma);
|
127
|
+
if (!NIL_P(value)) rb_funcall(self, ID_pragma, 1, value);
|
116
128
|
|
117
|
-
|
129
|
+
// :wal
|
130
|
+
value = rb_hash_aref(opts, SYM_wal);
|
118
131
|
if (RTEST(value)) {
|
119
|
-
|
120
|
-
|
132
|
+
int rc = sqlite3_exec(db->sqlite3_db, "PRAGMA journal_mode=wal", NULL, NULL, NULL);
|
133
|
+
if (rc != SQLITE_OK)
|
134
|
+
rb_raise(cError, "Failed to set WAL journaling mode: %s", sqlite3_errstr(rc));
|
135
|
+
rc = sqlite3_exec(db->sqlite3_db, "PRAGMA synchronous=1", NULL, NULL, NULL);
|
136
|
+
if (rc != SQLITE_OK)
|
137
|
+
rb_raise(cError, "Failed to set synchronous mode: %s", sqlite3_errstr(rc));
|
121
138
|
}
|
139
|
+
}
|
140
|
+
|
141
|
+
int Database_progress_handler(void *ptr) {
|
142
|
+
Database_t *db = (Database_t *)ptr;
|
143
|
+
db->progress_handler.tick_count += db->progress_handler.tick;
|
144
|
+
if (db->progress_handler.tick_count < db->progress_handler.period)
|
145
|
+
goto done;
|
146
|
+
|
147
|
+
db->progress_handler.tick_count -= db->progress_handler.period;
|
148
|
+
db->progress_handler.call_count += 1;
|
149
|
+
rb_funcall(db->progress_handler.proc, ID_call, 0);
|
150
|
+
done:
|
151
|
+
return 0;
|
152
|
+
}
|
122
153
|
|
123
|
-
|
154
|
+
int Database_busy_handler(void *ptr, int v) {
|
155
|
+
Database_t *db = (Database_t *)ptr;
|
156
|
+
rb_funcall(db->progress_handler.proc, ID_call, 1, Qtrue);
|
157
|
+
return 1;
|
124
158
|
}
|
125
159
|
|
126
|
-
/* Initializes a new SQLite database with the given path and options
|
160
|
+
/* Initializes a new SQLite database with the given path and options:
|
161
|
+
*
|
162
|
+
* - `:gvl_release_threshold` (`Integer`): sets the GVL release threshold (see
|
163
|
+
* `#gvl_release_threshold=`).
|
164
|
+
* - `:pragma` (`Hash`): one or more pragmas to set upon opening the database.
|
165
|
+
* - `:read_only` (`true`/`false`): opens the database in read-only mode if true.
|
166
|
+
* - `:wal` (`true`/`false`): sets up the database for [WAL journaling
|
167
|
+
* mode](https://www.sqlite.org/wal.html) by setting `PRAGMA journal_mode=wal`
|
168
|
+
* and `PRAGMA synchronous=1`.
|
127
169
|
*
|
128
170
|
* @overload initialize(path)
|
129
171
|
* @param path [String] file path (or ':memory:' for memory database)
|
130
172
|
* @return [void]
|
131
|
-
* @overload initialize(path, gvl_release_threshold: ,
|
173
|
+
* @overload initialize(path, gvl_release_threshold: , on_progress: , read_only: , wal: )
|
132
174
|
* @param path [String] file path (or ':memory:' for memory database)
|
133
|
-
* @param
|
134
|
-
* @param read_only [boolean] true for opening the database for reading only
|
135
|
-
* @param synchronous [boolean] true to set PRAGMA synchronous=1
|
136
|
-
* @param wal_journal_mode [boolean] true to set PRAGMA journal_mode=wal
|
175
|
+
* @param options [Hash] options for opening the database
|
137
176
|
* @return [void]
|
138
177
|
*/
|
139
178
|
VALUE Database_initialize(int argc, VALUE *argv, VALUE self) {
|
@@ -147,6 +186,7 @@ VALUE Database_initialize(int argc, VALUE *argv, VALUE self) {
|
|
147
186
|
int rc = sqlite3_open_v2(StringValueCStr(path), &db->sqlite3_db, flags, NULL);
|
148
187
|
if (rc) {
|
149
188
|
sqlite3_close_v2(db->sqlite3_db);
|
189
|
+
db->sqlite3_db = NULL;
|
150
190
|
rb_raise(cError, "%s", sqlite3_errstr(rc));
|
151
191
|
}
|
152
192
|
|
@@ -166,11 +206,19 @@ VALUE Database_initialize(int argc, VALUE *argv, VALUE self) {
|
|
166
206
|
#endif
|
167
207
|
|
168
208
|
db->trace_proc = Qnil;
|
169
|
-
db->progress_handler_proc = Qnil;
|
170
209
|
db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD;
|
171
210
|
|
172
|
-
|
211
|
+
db->progress_handler = global_progress_handler;
|
212
|
+
db->progress_handler.tick_count = 0;
|
213
|
+
db->progress_handler.call_count = 0;
|
214
|
+
if (db->progress_handler.mode != PROGRESS_NONE) {
|
215
|
+
db->gvl_release_threshold = -1;
|
216
|
+
if (db->progress_handler.mode != PROGRESS_ONCE)
|
217
|
+
sqlite3_progress_handler(db->sqlite3_db, db->progress_handler.tick, &Database_progress_handler, db);
|
218
|
+
sqlite3_busy_handler(db->sqlite3_db, &Database_busy_handler, db);
|
219
|
+
}
|
173
220
|
|
221
|
+
if (!NIL_P(opts)) Database_apply_opts(self, db, opts);
|
174
222
|
return Qnil;
|
175
223
|
}
|
176
224
|
|
@@ -184,10 +232,9 @@ VALUE Database_read_only_p(VALUE self) {
|
|
184
232
|
return (open == 1) ? Qtrue : Qfalse;
|
185
233
|
}
|
186
234
|
|
187
|
-
/*
|
188
|
-
*
|
189
|
-
*
|
190
|
-
* Closes the database.
|
235
|
+
/* Closes the database.
|
236
|
+
*
|
237
|
+
* @return [Extralite::Database] database
|
191
238
|
*/
|
192
239
|
VALUE Database_close(VALUE self) {
|
193
240
|
int rc;
|
@@ -198,7 +245,7 @@ VALUE Database_close(VALUE self) {
|
|
198
245
|
rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
199
246
|
}
|
200
247
|
|
201
|
-
db->sqlite3_db =
|
248
|
+
db->sqlite3_db = NULL;
|
202
249
|
return self;
|
203
250
|
}
|
204
251
|
|
@@ -218,24 +265,40 @@ inline enum gvl_mode Database_prepare_gvl_mode(Database_t *db) {
|
|
218
265
|
return db->gvl_release_threshold < 0 ? GVL_HOLD : GVL_RELEASE;
|
219
266
|
}
|
220
267
|
|
221
|
-
static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VALUE (*call)(query_ctx *)) {
|
268
|
+
static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VALUE (*call)(query_ctx *), enum query_mode query_mode) {
|
222
269
|
Database_t *db = self_to_open_database(self);
|
223
270
|
sqlite3_stmt *stmt;
|
224
|
-
VALUE sql;
|
225
|
-
|
271
|
+
VALUE sql = Qnil;
|
272
|
+
VALUE transform = Qnil;
|
273
|
+
// transform mode is set and the first parameter is not a string, so we expect
|
274
|
+
// a transform.
|
275
|
+
int got_transform = (TYPE(argv[0]) != T_STRING);
|
276
|
+
|
226
277
|
// extract query from args
|
227
|
-
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
278
|
+
rb_check_arity(argc, got_transform ? 2 : 1, UNLIMITED_ARGUMENTS);
|
279
|
+
|
280
|
+
if (got_transform) {
|
281
|
+
transform = argv[0];
|
282
|
+
argc--;
|
283
|
+
argv++;
|
284
|
+
}
|
285
|
+
|
228
286
|
sql = rb_funcall(argv[0], ID_strip, 0);
|
229
287
|
if (RSTRING_LEN(sql) == 0) return Qnil;
|
230
288
|
|
231
|
-
|
289
|
+
Database_issue_query(db, sql);
|
232
290
|
prepare_multi_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
|
233
291
|
RB_GC_GUARD(sql);
|
234
292
|
|
235
293
|
bind_all_parameters(stmt, argc - 1, argv + 1);
|
236
|
-
query_ctx ctx = QUERY_CTX(
|
237
|
-
|
238
|
-
|
294
|
+
query_ctx ctx = QUERY_CTX(
|
295
|
+
self, sql, db, stmt, Qnil, transform,
|
296
|
+
query_mode, ROW_YIELD_OR_MODE(ROW_MULTI), ALL_ROWS
|
297
|
+
);
|
298
|
+
|
299
|
+
VALUE result = rb_ensure(SAFE(call), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
|
300
|
+
RB_GC_GUARD(result);
|
301
|
+
return result;
|
239
302
|
}
|
240
303
|
|
241
304
|
/* call-seq:
|
@@ -254,21 +317,46 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA
|
|
254
317
|
* db.query('select * from foo where x = ?', 42)
|
255
318
|
*
|
256
319
|
* Named placeholders are specified using `:`. The placeholder values are
|
257
|
-
* specified using
|
258
|
-
* keys can include or omit the `:` prefix. The following are equivalent:
|
320
|
+
* specified using keyword arguments:
|
259
321
|
*
|
260
322
|
* db.query('select * from foo where x = :bar', bar: 42)
|
261
|
-
*
|
262
|
-
*
|
323
|
+
*
|
324
|
+
* @overload query(sql, ...)
|
325
|
+
* @param sql [String] SQL statement
|
326
|
+
* @return [Array<Hash>, Integer] rows or total changes
|
327
|
+
* @overload query(transform, sql, ...)
|
328
|
+
* @param transform [Proc] transform proc
|
329
|
+
* @param sql [String] SQL statement
|
330
|
+
* @return [Array<Hash>, Integer] rows or total changes
|
263
331
|
*/
|
264
|
-
VALUE
|
265
|
-
return Database_perform_query(argc, argv, self, safe_query_hash);
|
332
|
+
VALUE Database_query(int argc, VALUE *argv, VALUE self) {
|
333
|
+
return Database_perform_query(argc, argv, self, safe_query_hash, QUERY_HASH);
|
266
334
|
}
|
267
335
|
|
268
|
-
/*
|
269
|
-
*
|
336
|
+
/* Runs a query and transforms rows through the given transform poc. Each row is
|
337
|
+
* provided to the transform proc as a list of values. If a block is given, it
|
338
|
+
* will be called for each row. Otherwise, an array containing all rows is
|
339
|
+
* returned.
|
270
340
|
*
|
271
|
-
*
|
341
|
+
* If a transform block is given, it is called for each row, with the row values
|
342
|
+
* splatted:
|
343
|
+
*
|
344
|
+
* transform = ->(a, b, c) { a * 100 + b * 10 + c }
|
345
|
+
* db.query_argv(transform, 'select a, b, c from foo where c = ?', 42)
|
346
|
+
*
|
347
|
+
* @overload query_argv(sql, ...)
|
348
|
+
* @param sql [String] SQL statement
|
349
|
+
* @return [Array<Array, any>, Integer] rows or total changes
|
350
|
+
* @overload query_argv(transform, sql, ...)
|
351
|
+
* @param transform [Proc] transform proc
|
352
|
+
* @param sql [String] SQL statement
|
353
|
+
* @return [Array<Array, any>, Integer] rows or total changes
|
354
|
+
*/
|
355
|
+
VALUE Database_query_argv(int argc, VALUE *argv, VALUE self) {
|
356
|
+
return Database_perform_query(argc, argv, self, safe_query_argv, QUERY_ARGV);
|
357
|
+
}
|
358
|
+
|
359
|
+
/* Runs a query returning rows as arrays. If a block is given, it will be called
|
272
360
|
* for each row. Otherwise, an array containing all rows is returned.
|
273
361
|
*
|
274
362
|
* Query parameters to be bound to placeholders in the query can be specified as
|
@@ -285,82 +373,95 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
|
|
285
373
|
* db.query_ary('select * from foo where x = :bar', bar: 42)
|
286
374
|
* db.query_ary('select * from foo where x = :bar', 'bar' => 42)
|
287
375
|
* db.query_ary('select * from foo where x = :bar', ':bar' => 42)
|
376
|
+
*
|
377
|
+
* @overload query_ary(sql, ...)
|
378
|
+
* @param sql [String] SQL statement
|
379
|
+
* @return [Array<Array>, Integer] rows or total changes
|
380
|
+
* @overload query_ary(transform, sql, ...)
|
381
|
+
* @param transform [Proc] transform proc
|
382
|
+
* @param sql [String] SQL statement
|
383
|
+
* @return [Array<Array>, Integer] rows or total changes
|
288
384
|
*/
|
289
385
|
VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
|
290
|
-
return Database_perform_query(argc, argv, self, safe_query_ary);
|
386
|
+
return Database_perform_query(argc, argv, self, safe_query_ary, QUERY_ARY);
|
291
387
|
}
|
292
388
|
|
293
|
-
/*
|
294
|
-
* db.query_single_row(sql, *parameters) -> {...}
|
295
|
-
*
|
296
|
-
* Runs a query returning a single row as a hash.
|
389
|
+
/* Runs a query returning a single row as a hash.
|
297
390
|
*
|
298
391
|
* Query parameters to be bound to placeholders in the query can be specified as
|
299
392
|
* a list of values or as a hash mapping parameter names to values. When
|
300
393
|
* parameters are given as an array, the query should specify parameters using
|
301
394
|
* `?`:
|
302
395
|
*
|
303
|
-
* db.
|
396
|
+
* db.query_single('select * from foo where x = ?', 42)
|
304
397
|
*
|
305
398
|
* Named placeholders are specified using `:`. The placeholder values are
|
306
|
-
* specified using
|
307
|
-
* keys can include or omit the `:` prefix. The following are equivalent:
|
399
|
+
* specified using keyword arguments:
|
308
400
|
*
|
309
|
-
* db.
|
310
|
-
*
|
311
|
-
*
|
401
|
+
* db.query_single('select * from foo where x = :bar', bar: 42)
|
402
|
+
*
|
403
|
+
* @overload query_single(sql, ...) -> row
|
404
|
+
* @param sql [String] SQL statement
|
405
|
+
* @return [Array, any] row
|
406
|
+
* @overload query_single(transform, sql, ...) -> row
|
407
|
+
* @param transform [Proc] transform proc
|
408
|
+
* @param sql [String] SQL statement
|
409
|
+
* @return [Array, any] row
|
312
410
|
*/
|
313
|
-
VALUE
|
314
|
-
return Database_perform_query(argc, argv, self,
|
411
|
+
VALUE Database_query_single(int argc, VALUE *argv, VALUE self) {
|
412
|
+
return Database_perform_query(argc, argv, self, safe_query_single_row_hash, QUERY_HASH);
|
315
413
|
}
|
316
414
|
|
317
|
-
/*
|
318
|
-
* db.query_single_column(sql, *parameters, &block) -> [...]
|
319
|
-
*
|
320
|
-
* Runs a query returning single column values. If a block is given, it will be called
|
321
|
-
* for each value. Otherwise, an array containing all values is returned.
|
415
|
+
/* Runs a query returning a single row as an array or a single value.
|
322
416
|
*
|
323
417
|
* Query parameters to be bound to placeholders in the query can be specified as
|
324
418
|
* a list of values or as a hash mapping parameter names to values. When
|
325
419
|
* parameters are given as an array, the query should specify parameters using
|
326
420
|
* `?`:
|
327
421
|
*
|
328
|
-
* db.
|
422
|
+
* db.query_single_argv('select * from foo where x = ?', 42)
|
329
423
|
*
|
330
424
|
* Named placeholders are specified using `:`. The placeholder values are
|
331
|
-
* specified using
|
332
|
-
* keys can include or omit the `:` prefix. The following are equivalent:
|
425
|
+
* specified using keyword arguments:
|
333
426
|
*
|
334
|
-
* db.
|
335
|
-
*
|
336
|
-
*
|
427
|
+
* db.query_single_argv('select * from foo where x = :bar', bar: 42)
|
428
|
+
*
|
429
|
+
* @overload query_single_argv(sql, ...) -> row
|
430
|
+
* @param sql [String] SQL statement
|
431
|
+
* @return [Array, any] row
|
432
|
+
* @overload query_single_argv(transform, sql, ...) -> row
|
433
|
+
* @param transform [Proc] transform proc
|
434
|
+
* @param sql [String] SQL statement
|
435
|
+
* @return [Array, any] row
|
337
436
|
*/
|
338
|
-
VALUE
|
339
|
-
return Database_perform_query(argc, argv, self,
|
437
|
+
VALUE Database_query_single_argv(int argc, VALUE *argv, VALUE self) {
|
438
|
+
return Database_perform_query(argc, argv, self, safe_query_single_row_argv, QUERY_ARGV);
|
340
439
|
}
|
341
440
|
|
342
|
-
/*
|
343
|
-
* db.query_single_value(sql, *parameters) -> value
|
344
|
-
*
|
345
|
-
* Runs a query returning a single value from the first row.
|
441
|
+
/* Runs a query returning a single row as an array.
|
346
442
|
*
|
347
443
|
* Query parameters to be bound to placeholders in the query can be specified as
|
348
444
|
* a list of values or as a hash mapping parameter names to values. When
|
349
445
|
* parameters are given as an array, the query should specify parameters using
|
350
446
|
* `?`:
|
351
447
|
*
|
352
|
-
* db.
|
448
|
+
* db.query_single_ary('select * from foo where x = ?', 42)
|
353
449
|
*
|
354
450
|
* Named placeholders are specified using `:`. The placeholder values are
|
355
|
-
* specified using
|
356
|
-
* keys can include or omit the `:` prefix. The following are equivalent:
|
451
|
+
* specified using keyword arguments:
|
357
452
|
*
|
358
|
-
* db.
|
359
|
-
*
|
360
|
-
*
|
453
|
+
* db.query_single_ary('select * from foo where x = :bar', bar: 42)
|
454
|
+
*
|
455
|
+
* @overload query_single_ary(sql, ...) -> row
|
456
|
+
* @param sql [String] SQL statement
|
457
|
+
* @return [Array, any] row
|
458
|
+
* @overload query_single_ary(transform, sql, ...) -> row
|
459
|
+
* @param transform [Proc] transform proc
|
460
|
+
* @param sql [String] SQL statement
|
461
|
+
* @return [Array, any] row
|
361
462
|
*/
|
362
|
-
VALUE
|
363
|
-
return Database_perform_query(argc, argv, self,
|
463
|
+
VALUE Database_query_single_ary(int argc, VALUE *argv, VALUE self) {
|
464
|
+
return Database_perform_query(argc, argv, self, safe_query_single_row_ary, QUERY_ARY);
|
364
465
|
}
|
365
466
|
|
366
467
|
/* call-seq:
|
@@ -377,21 +478,16 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
|
377
478
|
* db.execute('update foo set x = ? where y = ?', 42, 43)
|
378
479
|
*
|
379
480
|
* Named placeholders are specified using `:`. The placeholder values are
|
380
|
-
* specified using
|
381
|
-
* keys can include or omit the `:` prefix. The following are equivalent:
|
481
|
+
* specified using keyword arguments:
|
382
482
|
*
|
383
483
|
* db.execute('update foo set x = :bar', bar: 42)
|
384
|
-
* db.execute('update foo set x = :bar', 'bar' => 42)
|
385
|
-
* db.execute('update foo set x = :bar', ':bar' => 42)
|
386
484
|
*/
|
387
485
|
VALUE Database_execute(int argc, VALUE *argv, VALUE self) {
|
388
|
-
return Database_perform_query(argc, argv, self, safe_query_changes);
|
486
|
+
return Database_perform_query(argc, argv, self, safe_query_changes, QUERY_HASH);
|
389
487
|
}
|
390
488
|
|
391
489
|
/* call-seq:
|
392
|
-
* db.batch_execute(sql,
|
393
|
-
* db.batch_execute(sql, enumerable) -> changes
|
394
|
-
* db.batch_execute(sql, callable) -> changes
|
490
|
+
* db.batch_execute(sql, params_source) -> changes
|
395
491
|
*
|
396
492
|
* Executes the given query for each list of parameters in the paramter source.
|
397
493
|
* If an enumerable is given, it is iterated and each of its values is used as
|
@@ -425,18 +521,17 @@ VALUE Database_batch_execute(VALUE self, VALUE sql, VALUE parameters) {
|
|
425
521
|
if (RSTRING_LEN(sql) == 0) return Qnil;
|
426
522
|
|
427
523
|
prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
|
428
|
-
query_ctx ctx = QUERY_CTX(
|
524
|
+
query_ctx ctx = QUERY_CTX(
|
525
|
+
self, sql, db, stmt, parameters,
|
526
|
+
Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS
|
527
|
+
);
|
429
528
|
|
430
529
|
return rb_ensure(SAFE(safe_batch_execute), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
|
431
530
|
}
|
432
531
|
|
433
532
|
/* call-seq:
|
434
|
-
* db.batch_query(sql,
|
435
|
-
* db.batch_query(sql,
|
436
|
-
* db.batch_query(sql, callable) -> rows
|
437
|
-
* db.batch_query(sql, params_array) { |rows| ... } -> changes
|
438
|
-
* db.batch_query(sql, enumerable) { |rows| ... } -> changes
|
439
|
-
* db.batch_query(sql, callable) { |rows| ... } -> changes
|
533
|
+
* db.batch_query(sql, params_source) -> rows
|
534
|
+
* db.batch_query(sql, params_source) { |rows| ... } -> changes
|
440
535
|
*
|
441
536
|
* Executes the given query for each list of parameters in the given paramter
|
442
537
|
* source. If a block is given, it is called with the resulting rows for each
|
@@ -460,18 +555,17 @@ VALUE Database_batch_query(VALUE self, VALUE sql, VALUE parameters) {
|
|
460
555
|
sqlite3_stmt *stmt;
|
461
556
|
|
462
557
|
prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
|
463
|
-
query_ctx ctx = QUERY_CTX(
|
558
|
+
query_ctx ctx = QUERY_CTX(
|
559
|
+
self, sql, db, stmt, parameters,
|
560
|
+
Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS
|
561
|
+
);
|
464
562
|
|
465
563
|
return rb_ensure(SAFE(safe_batch_query), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
|
466
564
|
}
|
467
565
|
|
468
566
|
/* call-seq:
|
469
|
-
* db.batch_query_ary(sql,
|
470
|
-
* db.batch_query_ary(sql,
|
471
|
-
* db.batch_query_ary(sql, callable) -> rows
|
472
|
-
* db.batch_query_ary(sql, params_array) { |rows| ... } -> changes
|
473
|
-
* db.batch_query_ary(sql, enumerable) { |rows| ... } -> changes
|
474
|
-
* db.batch_query_ary(sql, callable) { |rows| ... } -> changes
|
567
|
+
* db.batch_query_ary(sql, params_source) -> rows
|
568
|
+
* db.batch_query_ary(sql, params_source) { |rows| ... } -> changes
|
475
569
|
*
|
476
570
|
* Executes the given query for each list of parameters in the given paramter
|
477
571
|
* source. If a block is given, it is called with the resulting rows for each
|
@@ -495,18 +589,17 @@ VALUE Database_batch_query_ary(VALUE self, VALUE sql, VALUE parameters) {
|
|
495
589
|
sqlite3_stmt *stmt;
|
496
590
|
|
497
591
|
prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
|
498
|
-
query_ctx ctx = QUERY_CTX(
|
592
|
+
query_ctx ctx = QUERY_CTX(
|
593
|
+
self, sql, db, stmt, parameters,
|
594
|
+
Qnil, QUERY_ARY, ROW_MULTI, ALL_ROWS
|
595
|
+
);
|
499
596
|
|
500
597
|
return rb_ensure(SAFE(safe_batch_query_ary), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
|
501
598
|
}
|
502
599
|
|
503
600
|
/* call-seq:
|
504
|
-
* db.
|
505
|
-
* db.
|
506
|
-
* db.batch_query_single_column(sql, callable) -> rows
|
507
|
-
* db.batch_query_single_column(sql, params_array) { |rows| ... } -> changes
|
508
|
-
* db.batch_query_single_column(sql, enumerable) { |rows| ... } -> changes
|
509
|
-
* db.batch_query_single_column(sql, callable) { |rows| ... } -> changes
|
601
|
+
* db.batch_query_argv(sql, params_source) -> rows
|
602
|
+
* db.batch_query_argv(sql, params_source) { |rows| ... } -> changes
|
510
603
|
*
|
511
604
|
* Executes the given query for each list of parameters in the given paramter
|
512
605
|
* source. If a block is given, it is called with the resulting rows for each
|
@@ -518,36 +611,37 @@ VALUE Database_batch_query_ary(VALUE self, VALUE sql, VALUE parameters) {
|
|
518
611
|
* [1, 2],
|
519
612
|
* [3, 4]
|
520
613
|
* ]
|
521
|
-
* db.
|
614
|
+
* db.batch_query_argv('insert into foo values (?, ?) returning baz', records)
|
522
615
|
* #=> [2, 4]
|
523
616
|
* *
|
524
617
|
* @param sql [String] query SQL
|
525
618
|
* @param parameters [Array<Array, Hash>, Enumerable, Enumerator, Callable] parameters to run query with
|
526
619
|
* @return [Array<any>, Integer] Total number of changes effected
|
527
620
|
*/
|
528
|
-
VALUE
|
621
|
+
VALUE Database_batch_query_argv(VALUE self, VALUE sql, VALUE parameters) {
|
529
622
|
Database_t *db = self_to_open_database(self);
|
530
623
|
sqlite3_stmt *stmt;
|
531
624
|
|
532
625
|
prepare_single_stmt(DB_GVL_MODE(db), db->sqlite3_db, &stmt, sql);
|
533
|
-
query_ctx ctx = QUERY_CTX(
|
626
|
+
query_ctx ctx = QUERY_CTX(
|
627
|
+
self, sql, db, stmt, parameters,
|
628
|
+
Qnil, QUERY_ARGV, ROW_MULTI, ALL_ROWS
|
629
|
+
);
|
534
630
|
|
535
|
-
return rb_ensure(SAFE(
|
631
|
+
return rb_ensure(SAFE(safe_batch_query_argv), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
|
536
632
|
}
|
537
633
|
|
538
|
-
/*
|
539
|
-
*
|
540
|
-
*
|
541
|
-
* Returns the column names for the given query, without running it.
|
634
|
+
/* Returns the column names for the given query, without running it.
|
635
|
+
*
|
636
|
+
* @return [Array<String>] column names
|
542
637
|
*/
|
543
638
|
VALUE Database_columns(VALUE self, VALUE sql) {
|
544
|
-
return Database_perform_query(1, &sql, self, safe_query_columns);
|
639
|
+
return Database_perform_query(1, &sql, self, safe_query_columns, QUERY_HASH);
|
545
640
|
}
|
546
641
|
|
547
|
-
/*
|
548
|
-
*
|
549
|
-
*
|
550
|
-
* Returns the rowid of the last inserted row.
|
642
|
+
/* Returns the rowid of the last inserted row.
|
643
|
+
*
|
644
|
+
* @return [Integer] last rowid
|
551
645
|
*/
|
552
646
|
VALUE Database_last_insert_rowid(VALUE self) {
|
553
647
|
Database_t *db = self_to_open_database(self);
|
@@ -555,10 +649,9 @@ VALUE Database_last_insert_rowid(VALUE self) {
|
|
555
649
|
return INT2FIX(sqlite3_last_insert_rowid(db->sqlite3_db));
|
556
650
|
}
|
557
651
|
|
558
|
-
/*
|
559
|
-
*
|
560
|
-
*
|
561
|
-
* Returns the number of changes made to the database by the last operation.
|
652
|
+
/* Returns the number of changes made to the database by the last operation.
|
653
|
+
*
|
654
|
+
* @return [Integer] number of changes
|
562
655
|
*/
|
563
656
|
VALUE Database_changes(VALUE self) {
|
564
657
|
Database_t *db = self_to_open_database(self);
|
@@ -566,10 +659,14 @@ VALUE Database_changes(VALUE self) {
|
|
566
659
|
return INT2FIX(sqlite3_changes(db->sqlite3_db));
|
567
660
|
}
|
568
661
|
|
569
|
-
/*
|
570
|
-
*
|
571
|
-
* Returns the database filename. If db_name is given, returns the filename for
|
662
|
+
/* Returns the database filename. If db_name is given, returns the filename for
|
572
663
|
* the respective attached database.
|
664
|
+
*
|
665
|
+
* @overload filename()
|
666
|
+
* @return [String] database filename
|
667
|
+
* @overload filename(db_name)
|
668
|
+
* @param db_name [String] attached database name
|
669
|
+
* @return [String] database filename
|
573
670
|
*/
|
574
671
|
VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
|
575
672
|
const char *db_name;
|
@@ -582,10 +679,9 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
|
|
582
679
|
return filename ? rb_str_new_cstr(filename) : Qnil;
|
583
680
|
}
|
584
681
|
|
585
|
-
/*
|
586
|
-
*
|
587
|
-
*
|
588
|
-
* Returns true if a transaction is currently in progress.
|
682
|
+
/* Returns true if a transaction is currently in progress.
|
683
|
+
*
|
684
|
+
* @return [bool] is transaction in progress
|
589
685
|
*/
|
590
686
|
VALUE Database_transaction_active_p(VALUE self) {
|
591
687
|
Database_t *db = self_to_open_database(self);
|
@@ -594,10 +690,10 @@ VALUE Database_transaction_active_p(VALUE self) {
|
|
594
690
|
}
|
595
691
|
|
596
692
|
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
597
|
-
/*
|
598
|
-
*
|
599
|
-
*
|
600
|
-
*
|
693
|
+
/* Loads an extension with the given path.
|
694
|
+
*
|
695
|
+
* @param path [String] extension file path
|
696
|
+
* @return [Extralite::Database] database
|
601
697
|
*/
|
602
698
|
VALUE Database_load_extension(VALUE self, VALUE path) {
|
603
699
|
Database_t *db = self_to_open_database(self);
|
@@ -614,30 +710,76 @@ VALUE Database_load_extension(VALUE self, VALUE path) {
|
|
614
710
|
}
|
615
711
|
#endif
|
616
712
|
|
617
|
-
|
618
|
-
* db.prepare(sql) -> Extralite::Query
|
619
|
-
* db.prepare(sql, ...) -> Extralite::Query
|
620
|
-
*
|
621
|
-
* Creates a prepared statement with the given SQL query. If query parameters
|
622
|
-
* are given, they are bound to the query.
|
623
|
-
*/
|
624
|
-
VALUE Database_prepare(int argc, VALUE *argv, VALUE self) {
|
713
|
+
static inline VALUE Database_prepare(int argc, VALUE *argv, VALUE self, VALUE mode) {
|
625
714
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
626
|
-
|
715
|
+
|
716
|
+
VALUE args[] = { self, argv[0], mode};
|
717
|
+
VALUE query = rb_funcall_passing_block(cQuery, ID_new, 3, args);
|
627
718
|
if (argc > 1) rb_funcallv(query, ID_bind, argc - 1, argv + 1);
|
628
719
|
RB_GC_GUARD(query);
|
629
720
|
return query;
|
630
721
|
}
|
631
722
|
|
632
723
|
/* call-seq:
|
633
|
-
* db.
|
724
|
+
* db.prepare(sql) -> query
|
725
|
+
* db.prepare(sql, *params) -> query
|
726
|
+
* db.prepare(sql, *params) { ... } -> query
|
634
727
|
*
|
635
|
-
*
|
728
|
+
* Creates a prepared query with the given SQL query in hash mode. If query
|
729
|
+
* parameters are given, they are bound to the query. If a block is given, it is
|
730
|
+
* used as a transform proc.
|
731
|
+
*
|
732
|
+
* @param sql [String] SQL statement
|
733
|
+
* @param *params [Array<any>] parameters to bind
|
734
|
+
* @return [Extralite::Query] prepared query
|
735
|
+
*/
|
736
|
+
VALUE Database_prepare_hash(int argc, VALUE *argv, VALUE self) {
|
737
|
+
return Database_prepare(argc, argv, self, SYM_hash);
|
738
|
+
}
|
739
|
+
|
740
|
+
/* call-seq:
|
741
|
+
* db.prepare_argv(sql) -> Extralite::Query
|
742
|
+
* db.prepare_argv(sql, *params) -> Extralite::Query
|
743
|
+
* db.prepare_argv(sql, *params) { ... } -> Extralite::Query
|
744
|
+
*
|
745
|
+
* Creates a prepared query with the given SQL query in argv mode. If query
|
746
|
+
* parameters are given, they are bound to the query. If a block is given, it is
|
747
|
+
* used as a transform proc.
|
748
|
+
*
|
749
|
+
* @param sql [String] SQL statement
|
750
|
+
* @param *params [Array<any>] parameters to bind
|
751
|
+
* @return [Extralite::Query] prepared query
|
752
|
+
*/
|
753
|
+
VALUE Database_prepare_argv(int argc, VALUE *argv, VALUE self) {
|
754
|
+
return Database_prepare(argc, argv, self, SYM_argv);
|
755
|
+
}
|
756
|
+
|
757
|
+
/* call-seq:
|
758
|
+
* db.prepare_ary(sql) -> Extralite::Query
|
759
|
+
* db.prepare_ary(sql, *params) -> Extralite::Query
|
760
|
+
* db.prepare_ary(sql, *params) { ... } -> Extralite::Query
|
761
|
+
*
|
762
|
+
* Creates a prepared query with the given SQL query in ary mode. If query
|
763
|
+
* parameters are given, they are bound to the query. If a block is given, it is
|
764
|
+
* used as a transform proc.
|
765
|
+
*
|
766
|
+
* @param sql [String] SQL statement
|
767
|
+
* @param *params [Array<any>] parameters to bind
|
768
|
+
* @return [Extralite::Query] prepared query
|
769
|
+
*/
|
770
|
+
VALUE Database_prepare_ary(int argc, VALUE *argv, VALUE self) {
|
771
|
+
return Database_prepare(argc, argv, self, SYM_ary);
|
772
|
+
}
|
773
|
+
|
774
|
+
/* Interrupts a long running query. This method is to be called from a different
|
636
775
|
* thread than the one running the query. Upon calling `#interrupt` the running
|
637
776
|
* query will stop and raise an `Extralite::InterruptError` exception.
|
638
777
|
*
|
639
778
|
* It is not safe to call `#interrupt` on a database that is about to be closed.
|
640
|
-
* For more information, consult the [sqlite3 API
|
779
|
+
* For more information, consult the [sqlite3 API
|
780
|
+
* docs](https://sqlite.org/c3ref/interrupt.html).
|
781
|
+
*
|
782
|
+
* @return [Extralite::Database] database
|
641
783
|
*/
|
642
784
|
VALUE Database_interrupt(VALUE self) {
|
643
785
|
Database_t *db = self_to_open_database(self);
|
@@ -712,15 +854,24 @@ VALUE backup_cleanup(VALUE ptr) {
|
|
712
854
|
}
|
713
855
|
|
714
856
|
/* call-seq:
|
715
|
-
* db.backup(dest) -> db
|
716
|
-
* db.backup(dest) { |remaining, total| } -> db
|
857
|
+
* db.backup(dest, src_db_name = 'main', dst_db_name = 'main') { |remaining, total| ... } -> db
|
717
858
|
*
|
859
|
+
*
|
718
860
|
* Creates a backup of the database to the given destination, which can be
|
719
861
|
* either a filename or a database instance. In order to monitor the backup
|
720
862
|
* progress you can pass a block that will be called periodically by the backup
|
721
863
|
* method with two arguments: the remaining page count, and the total page
|
722
864
|
* count, which can be used to display the progress to the user or to collect
|
723
865
|
* statistics.
|
866
|
+
*
|
867
|
+
* db_src.backup(db_dest) do |remaining, total|
|
868
|
+
* puts "Backing up #{remaining}/#{total}"
|
869
|
+
* end
|
870
|
+
*
|
871
|
+
* @param dest [String, Extralite::Database] backup destination
|
872
|
+
* @param src_db_name [String] source database name (default: "main")
|
873
|
+
* @param dst_db_name [String] Destination database name (default: "main")
|
874
|
+
* @return [Extralite::Database] source database
|
724
875
|
*/
|
725
876
|
VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
|
726
877
|
VALUE dst;
|
@@ -766,12 +917,17 @@ VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
|
|
766
917
|
return self;
|
767
918
|
}
|
768
919
|
|
769
|
-
/*
|
770
|
-
* Extralite.runtime_status(op[, reset]) -> [value, highwatermark]
|
771
|
-
*
|
772
|
-
* Returns runtime status values for the given op as an array containing the
|
920
|
+
/* Returns runtime status values for the given op as an array containing the
|
773
921
|
* current value and the high water mark value. To reset the high water mark,
|
774
922
|
* pass true as reset.
|
923
|
+
*
|
924
|
+
* @overload runtime_status(op)
|
925
|
+
* @param op [Integer] op
|
926
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
927
|
+
* @overload runtime_status(op, reset)
|
928
|
+
* @param op [Integer] op
|
929
|
+
* @param reset [Integer, bool] reset flag
|
930
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
775
931
|
*/
|
776
932
|
VALUE Extralite_runtime_status(int argc, VALUE* argv, VALUE self) {
|
777
933
|
VALUE op, reset;
|
@@ -785,12 +941,17 @@ VALUE Extralite_runtime_status(int argc, VALUE* argv, VALUE self) {
|
|
785
941
|
return rb_ary_new3(2, LONG2FIX(cur), LONG2FIX(hwm));
|
786
942
|
}
|
787
943
|
|
788
|
-
/*
|
789
|
-
* db.status(op[, reset]) -> [value, highwatermark]
|
790
|
-
*
|
791
|
-
* Returns database status values for the given op as an array containing the
|
944
|
+
/* Returns database status values for the given op as an array containing the
|
792
945
|
* current value and the high water mark value. To reset the high water mark,
|
793
946
|
* pass true as reset.
|
947
|
+
*
|
948
|
+
* @overload status(op)
|
949
|
+
* @param op [Integer] op
|
950
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
951
|
+
* @overload status(op, reset)
|
952
|
+
* @param op [Integer] op
|
953
|
+
* @param reset [Integer, bool] reset flag
|
954
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
794
955
|
*/
|
795
956
|
VALUE Database_status(int argc, VALUE *argv, VALUE self) {
|
796
957
|
VALUE op, reset;
|
@@ -806,12 +967,16 @@ VALUE Database_status(int argc, VALUE *argv, VALUE self) {
|
|
806
967
|
return rb_ary_new3(2, INT2NUM(cur), INT2NUM(hwm));
|
807
968
|
}
|
808
969
|
|
809
|
-
/*
|
810
|
-
* db.limit(category) -> value
|
811
|
-
* db.limit(category, new_value) -> prev_value
|
812
|
-
*
|
813
|
-
* Returns the current limit for the given category. If a new value is given,
|
970
|
+
/* Returns the current limit for the given category. If a new value is given,
|
814
971
|
* sets the limit to the new value and returns the previous value.
|
972
|
+
*
|
973
|
+
* @overload limit(category)
|
974
|
+
* @param category [Integer] category
|
975
|
+
* @return [Integer] limit value
|
976
|
+
* @overload limit(category, new_value)
|
977
|
+
* @param category [Integer] category
|
978
|
+
* @param new_value [Integer] new value
|
979
|
+
* @return [Integer] old value
|
815
980
|
*/
|
816
981
|
VALUE Database_limit(int argc, VALUE *argv, VALUE self) {
|
817
982
|
VALUE category, new_value;
|
@@ -827,12 +992,18 @@ VALUE Database_limit(int argc, VALUE *argv, VALUE self) {
|
|
827
992
|
return INT2NUM(value);
|
828
993
|
}
|
829
994
|
|
830
|
-
/*
|
831
|
-
*
|
832
|
-
*
|
995
|
+
/* Sets the busy timeout for the database, in seconds or fractions thereof. To
|
996
|
+
* disable the busy timeout, set it to 0 or nil. When the busy timeout is set to
|
997
|
+
* a value larger than zero, running a query when the database is locked will
|
998
|
+
* cause the program to wait for the database to become available. If the
|
999
|
+
* database is still locked when the timeout period has elapsed, the query will
|
1000
|
+
* fail with a `Extralite::BusyError` exception.
|
1001
|
+
*
|
1002
|
+
* Setting the busy timeout allows other threads to run while waiting for the
|
1003
|
+
* database to become available. See also `#on_progress`.
|
833
1004
|
*
|
834
|
-
*
|
835
|
-
*
|
1005
|
+
* @param sec [Number, nil] timeout value
|
1006
|
+
* @return [Extralite::Database] database
|
836
1007
|
*/
|
837
1008
|
VALUE Database_busy_timeout_set(VALUE self, VALUE sec) {
|
838
1009
|
Database_t *db = self_to_open_database(self);
|
@@ -844,10 +1015,9 @@ VALUE Database_busy_timeout_set(VALUE self, VALUE sec) {
|
|
844
1015
|
return self;
|
845
1016
|
}
|
846
1017
|
|
847
|
-
/*
|
848
|
-
*
|
849
|
-
*
|
850
|
-
* Returns the total number of changes made to the database since opening it.
|
1018
|
+
/* Returns the total number of changes made to the database since opening it.
|
1019
|
+
*
|
1020
|
+
* @return [Integer] total changes
|
851
1021
|
*/
|
852
1022
|
VALUE Database_total_changes(VALUE self) {
|
853
1023
|
Database_t *db = self_to_open_database(self);
|
@@ -856,12 +1026,10 @@ VALUE Database_total_changes(VALUE self) {
|
|
856
1026
|
return INT2NUM(value);
|
857
1027
|
}
|
858
1028
|
|
859
|
-
/*
|
860
|
-
*
|
861
|
-
*
|
862
|
-
*
|
863
|
-
* Installs or removes a block that will be invoked for every SQL statement
|
864
|
-
* executed.
|
1029
|
+
/* Installs or removes a block that will be invoked for every SQL statement
|
1030
|
+
* executed. To stop tracing, call `#trace` without a block.
|
1031
|
+
*
|
1032
|
+
* @return [Extralite::Database] database
|
865
1033
|
*/
|
866
1034
|
VALUE Database_trace(VALUE self) {
|
867
1035
|
Database_t *db = self_to_open_database(self);
|
@@ -871,18 +1039,21 @@ VALUE Database_trace(VALUE self) {
|
|
871
1039
|
}
|
872
1040
|
|
873
1041
|
#ifdef EXTRALITE_ENABLE_CHANGESET
|
874
|
-
/*
|
1042
|
+
/* call-seq:
|
1043
|
+
* db.track_changes(*tables) { ... } -> changeset
|
1044
|
+
*
|
1045
|
+
* Tracks changes to the database and returns a changeset. The changeset can
|
875
1046
|
* then be used to store the changes to a file, apply them to another database,
|
876
1047
|
* or undo the changes. The given table names specify which tables should be
|
877
1048
|
* tracked for changes. Passing a value of nil causes all tables to be tracked.
|
878
1049
|
*
|
879
|
-
*
|
880
|
-
*
|
881
|
-
*
|
1050
|
+
* changeset = db.track_changes(:foo, :bar) do
|
1051
|
+
* perform_a_bunch_of_queries
|
1052
|
+
* end
|
882
1053
|
*
|
883
|
-
*
|
1054
|
+
* File.open('my.changes', 'w+') { |f| f << changeset.to_blob }
|
884
1055
|
*
|
885
|
-
* @param
|
1056
|
+
* @param *tables [Array<String, Symbol>] table(s) to track
|
886
1057
|
* @return [Extralite::Changeset] changeset
|
887
1058
|
*/
|
888
1059
|
VALUE Database_track_changes(int argc, VALUE *argv, VALUE self) {
|
@@ -899,101 +1070,239 @@ VALUE Database_track_changes(int argc, VALUE *argv, VALUE self) {
|
|
899
1070
|
}
|
900
1071
|
#endif
|
901
1072
|
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
1073
|
+
void Database_reset_progress_handler(VALUE self, Database_t *db) {
|
1074
|
+
db->progress_handler.mode = PROGRESS_NONE;
|
1075
|
+
RB_OBJ_WRITE(self, &db->progress_handler.proc, Qnil);
|
1076
|
+
sqlite3_progress_handler(db->sqlite3_db, 0, NULL, NULL);
|
1077
|
+
sqlite3_busy_handler(db->sqlite3_db, NULL, NULL);
|
906
1078
|
}
|
907
1079
|
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
return
|
1080
|
+
static inline enum progress_handler_mode symbol_to_progress_mode(VALUE mode) {
|
1081
|
+
if (mode == SYM_at_least_once) return PROGRESS_AT_LEAST_ONCE;
|
1082
|
+
if (mode == SYM_once) return PROGRESS_ONCE;
|
1083
|
+
if (mode == SYM_normal) return PROGRESS_NORMAL;
|
1084
|
+
if (mode == SYM_none) return PROGRESS_NONE;
|
1085
|
+
rb_raise(eArgumentError, "Invalid progress handler mode");
|
912
1086
|
}
|
913
1087
|
|
914
|
-
void
|
915
|
-
|
916
|
-
|
917
|
-
|
1088
|
+
inline void Database_issue_query(Database_t *db, VALUE sql) {
|
1089
|
+
if (db->trace_proc != Qnil) rb_funcall(db->trace_proc, ID_call, 1, sql);
|
1090
|
+
switch (db->progress_handler.mode) {
|
1091
|
+
case PROGRESS_AT_LEAST_ONCE:
|
1092
|
+
case PROGRESS_ONCE:
|
1093
|
+
rb_funcall(db->progress_handler.proc, ID_call, 0);
|
1094
|
+
default:
|
1095
|
+
; // do nothing
|
1096
|
+
|
1097
|
+
}
|
918
1098
|
}
|
919
1099
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
1100
|
+
struct progress_handler parse_progress_handler_opts(VALUE opts) {
|
1101
|
+
static ID kw_ids[3];
|
1102
|
+
VALUE kw_args[3];
|
1103
|
+
struct progress_handler prog = {
|
1104
|
+
.mode = rb_block_given_p() ? PROGRESS_NORMAL : PROGRESS_NONE,
|
1105
|
+
.proc = rb_block_given_p() ? rb_block_proc() : Qnil,
|
1106
|
+
.period = DEFAULT_PROGRESS_HANDLER_PERIOD,
|
1107
|
+
.tick = DEFAULT_PROGRESS_HANDLER_TICK
|
1108
|
+
};
|
1109
|
+
|
1110
|
+
if (!NIL_P(opts)) {
|
1111
|
+
if (!kw_ids[0]) {
|
1112
|
+
CONST_ID(kw_ids[0], "period");
|
1113
|
+
CONST_ID(kw_ids[1], "tick");
|
1114
|
+
CONST_ID(kw_ids[2], "mode");
|
1115
|
+
}
|
1116
|
+
|
1117
|
+
rb_get_kwargs(opts, kw_ids, 0, 3, kw_args);
|
1118
|
+
if (kw_args[0] != Qundef) { prog.period = NUM2INT(kw_args[0]); }
|
1119
|
+
if (kw_args[1] != Qundef) { prog.tick = NUM2INT(kw_args[1]); }
|
1120
|
+
if (kw_args[2] != Qundef) { prog.mode = symbol_to_progress_mode(kw_args[2]); }
|
1121
|
+
if (prog.tick > prog.period) prog.tick = prog.period;
|
1122
|
+
}
|
1123
|
+
if (NIL_P(prog.proc) || (prog.period <= 0)) prog.mode = PROGRESS_NONE;
|
1124
|
+
if (prog.mode == PROGRESS_NONE) prog.proc = Qnil;
|
1125
|
+
|
1126
|
+
return prog;
|
1127
|
+
}
|
1128
|
+
|
1129
|
+
/* Installs or removes a progress handler that will be executed periodically
|
925
1130
|
* while a query is running. This method can be used to support switching
|
926
1131
|
* between fibers and threads or implementing timeouts for running queries.
|
927
1132
|
*
|
928
|
-
* The
|
929
|
-
* machine instructions that are evaluated between successive
|
930
|
-
* progress handler. A period of less than 1 removes the
|
1133
|
+
* The `period` parameter specifies the approximate number of SQLite
|
1134
|
+
* virtual machine instructions that are evaluated between successive
|
1135
|
+
* invocations of the progress handler. A period of less than 1 removes the
|
1136
|
+
* progress handler. The default period value is 1000.
|
1137
|
+
*
|
1138
|
+
* The optional `tick` parameter specifies the granularity of how often the
|
1139
|
+
* progress handler is called. The default tick value is 10, which means that
|
1140
|
+
* Extralite's underlying progress callback will be called every 10 SQLite VM
|
1141
|
+
* instructions. The given progress proc, however, will be only called every
|
1142
|
+
* `period` (cumulative) VM instructions. This allows the progress handler to
|
1143
|
+
* work correctly also when running simple queries that don't include many
|
1144
|
+
* VM instructions. If the `tick` value is greater than the period value it is
|
1145
|
+
* automatically capped to the period value.
|
1146
|
+
*
|
1147
|
+
* The `mode` parameter controls the progress handler mode, which is one of the
|
1148
|
+
* following:
|
1149
|
+
*
|
1150
|
+
* - `:normal` (default): the progress handler proc is invoked on query
|
1151
|
+
* progress.
|
1152
|
+
* - `:once`: the progress handler proc is invoked only once, when preparing the
|
1153
|
+
* query.
|
1154
|
+
* - `:at_least_once`: the progress handler proc is invoked when prearing the
|
1155
|
+
* query, and on query progress.
|
931
1156
|
*
|
932
1157
|
* The progress handler is called also when the database is busy. This lets the
|
933
1158
|
* application perform work while waiting for the database to become unlocked,
|
934
1159
|
* or implement a timeout. Note that setting the database's busy_timeout _after_
|
935
1160
|
* setting a progress handler may lead to undefined behaviour in a concurrent
|
936
|
-
* application.
|
1161
|
+
* application. When busy, the progress handler proc is passed `true` as the
|
1162
|
+
* first argument.
|
937
1163
|
*
|
938
1164
|
* When the progress handler is set, the gvl release threshold value is set to
|
939
1165
|
* -1, which means that the GVL will not be released at all when preparing or
|
940
1166
|
* running queries. It is the application's responsibility to let other threads
|
941
1167
|
* or fibers run by calling e.g. Thread.pass:
|
942
|
-
*
|
943
|
-
* db.on_progress
|
1168
|
+
*
|
1169
|
+
* db.on_progress do
|
944
1170
|
* do_something_interesting
|
945
1171
|
* Thread.pass # let other threads run
|
946
1172
|
* end
|
947
|
-
*
|
948
|
-
* Note that the progress handler is set globally for the database and that
|
1173
|
+
*
|
1174
|
+
* Note that the progress handler is set globally for the database and that
|
949
1175
|
* Extralite does provide any hooks for telling which queries are currently
|
950
|
-
* running or at what time they were started. This means that you'll need
|
951
|
-
*
|
1176
|
+
* running or at what time they were started. This means that you'll need to
|
1177
|
+
* wrap the stock #query_xxx and #execute methods with your own code that
|
952
1178
|
* calculates timeouts, for example:
|
953
|
-
*
|
1179
|
+
*
|
954
1180
|
* def setup_progress_handler
|
955
|
-
* @db.on_progress
|
1181
|
+
* @db.on_progress do
|
956
1182
|
* raise TimeoutError if Time.now - @t0 >= @timeout
|
957
1183
|
* Thread.pass
|
958
1184
|
* end
|
959
1185
|
* end
|
960
|
-
*
|
1186
|
+
*
|
961
1187
|
* def query(sql, *)
|
962
1188
|
* @t0 = Time.now
|
963
1189
|
* @db.query(sql, *)
|
964
1190
|
* end
|
965
|
-
*
|
1191
|
+
*
|
966
1192
|
* If the gvl release threshold is set to a value equal to or larger than 0
|
967
1193
|
* after setting the progress handler, the progress handler will be reset.
|
968
1194
|
*
|
969
1195
|
* @param period [Integer] progress handler period
|
970
|
-
* @
|
1196
|
+
* @param [Hash] opts progress options
|
1197
|
+
* @option opts [Integer] :period period value (`1000` by default)
|
1198
|
+
* @option opts [Integer] :tick tick value (`10` by default)
|
1199
|
+
* @option opts [Symbol] :mode progress handler mode (`:normal` by default)
|
1200
|
+
* @return [Extralite::Database] database
|
971
1201
|
*/
|
972
|
-
VALUE Database_on_progress(VALUE
|
1202
|
+
VALUE Database_on_progress(int argc, VALUE *argv, VALUE self) {
|
973
1203
|
Database_t *db = self_to_open_database(self);
|
974
|
-
|
1204
|
+
VALUE opts;
|
1205
|
+
struct progress_handler prog;
|
975
1206
|
|
976
|
-
|
977
|
-
|
978
|
-
db->gvl_release_threshold = -1;
|
1207
|
+
rb_scan_args(argc, argv, "00:", &opts);
|
1208
|
+
prog = parse_progress_handler_opts(opts);
|
979
1209
|
|
980
|
-
|
981
|
-
|
982
|
-
}
|
983
|
-
else {
|
984
|
-
RB_OBJ_WRITE(self, &db->progress_handler_proc, Qnil);
|
1210
|
+
if (prog.mode == PROGRESS_NONE) {
|
1211
|
+
Database_reset_progress_handler(self, db);
|
985
1212
|
db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD;
|
986
|
-
|
987
|
-
sqlite3_busy_handler(db->sqlite3_db, NULL, NULL);
|
1213
|
+
return self;
|
988
1214
|
}
|
989
1215
|
|
1216
|
+
db->gvl_release_threshold = -1;
|
1217
|
+
db->progress_handler.mode = prog.mode;
|
1218
|
+
RB_OBJ_WRITE(self, &db->progress_handler.proc, prog.proc);
|
1219
|
+
db->progress_handler.period = prog.period;
|
1220
|
+
db->progress_handler.tick = prog.tick;
|
1221
|
+
db->progress_handler.tick_count = 0;
|
1222
|
+
db->progress_handler.call_count = 0;
|
1223
|
+
|
1224
|
+
// The PROGRESS_ONCE mode works by invoking the progress handler proc exactly
|
1225
|
+
// once, before iterating over the result set, so in that mode we don't
|
1226
|
+
// actually need to set the progress handler at the sqlite level.
|
1227
|
+
if (prog.mode != PROGRESS_ONCE)
|
1228
|
+
sqlite3_progress_handler(db->sqlite3_db, prog.tick, &Database_progress_handler, db);
|
1229
|
+
if (prog.mode != PROGRESS_NONE)
|
1230
|
+
sqlite3_busy_handler(db->sqlite3_db, &Database_busy_handler, db);
|
1231
|
+
|
990
1232
|
return self;
|
991
1233
|
}
|
992
1234
|
|
993
1235
|
/* call-seq:
|
994
|
-
*
|
1236
|
+
* Extralite.on_progress(**opts) { ... }
|
1237
|
+
*
|
1238
|
+
* Installs or removes a global progress handler that will be executed
|
1239
|
+
* periodically while a query is running. This method can be used to support
|
1240
|
+
* switching between fibers and threads or implementing timeouts for running
|
1241
|
+
* queries.
|
1242
|
+
*
|
1243
|
+
* This method sets the progress handler settings and behaviour for all
|
1244
|
+
* subsequently created `Database` instances. Calling this method will have no
|
1245
|
+
* effect on already existing `Database` instances
|
1246
|
+
*
|
1247
|
+
* The `period` parameter specifies the approximate number of SQLite
|
1248
|
+
* virtual machine instructions that are evaluated between successive
|
1249
|
+
* invocations of the progress handler. A period of less than 1 removes the
|
1250
|
+
* progress handler. The default period value is 1000.
|
1251
|
+
*
|
1252
|
+
* The optional `tick` parameter specifies the granularity of how often the
|
1253
|
+
* progress handler is called. The default tick value is 10, which means that
|
1254
|
+
* Extralite's underlying progress callback will be called every 10 SQLite VM
|
1255
|
+
* instructions. The given progress proc, however, will be only called every
|
1256
|
+
* `period` (cumulative) VM instructions. This allows the progress handler to
|
1257
|
+
* work correctly also when running simple queries that don't include many
|
1258
|
+
* VM instructions. If the `tick` value is greater than the period value it is
|
1259
|
+
* automatically capped to the period value.
|
1260
|
+
*
|
1261
|
+
* The `mode` parameter controls the progress handler mode, which is one of the
|
1262
|
+
* following:
|
1263
|
+
*
|
1264
|
+
* - `:normal` (default): the progress handler proc is invoked on query
|
1265
|
+
* progress.
|
1266
|
+
* - `:once`: the progress handler proc is invoked only once, when preparing the
|
1267
|
+
* query.
|
1268
|
+
* - `:at_least_once`: the progress handler proc is invoked when prearing the
|
1269
|
+
* query, and on query progress.
|
1270
|
+
*
|
1271
|
+
* The progress handler is called also when the database is busy. This lets the
|
1272
|
+
* application perform work while waiting for the database to become unlocked,
|
1273
|
+
* or implement a timeout. Note that setting the database's busy_timeout _after_
|
1274
|
+
* setting a progress handler may lead to undefined behaviour in a concurrent
|
1275
|
+
* application. When busy, the progress handler proc is passed `true` as the
|
1276
|
+
* first argument.
|
1277
|
+
*
|
1278
|
+
* When the progress handler is set, the gvl release threshold value is set to
|
1279
|
+
* -1, which means that the GVL will not be released at all when preparing or
|
1280
|
+
* running queries. It is the application's responsibility to let other threads
|
1281
|
+
* or fibers run by calling e.g. Thread.pass:
|
1282
|
+
*
|
1283
|
+
* Extralite.on_progress do
|
1284
|
+
* do_something_interesting
|
1285
|
+
* Thread.pass # let other threads run
|
1286
|
+
* end
|
995
1287
|
*
|
996
|
-
*
|
1288
|
+
* @param period [Integer] progress handler period
|
1289
|
+
* @param [Hash] opts progress options
|
1290
|
+
* @option opts [Integer] :period period value (`1000` by default)
|
1291
|
+
* @option opts [Integer] :tick tick value (`10` by default)
|
1292
|
+
* @option opts [Symbol] :mode progress handler mode (`:normal` by default)
|
1293
|
+
* @return [Extralite::Database] database
|
1294
|
+
*/
|
1295
|
+
VALUE Extralite_on_progress(int argc, VALUE *argv, VALUE self) {
|
1296
|
+
VALUE opts;
|
1297
|
+
|
1298
|
+
rb_scan_args(argc, argv, "00:", &opts);
|
1299
|
+
global_progress_handler = parse_progress_handler_opts(opts);
|
1300
|
+
return self;
|
1301
|
+
}
|
1302
|
+
|
1303
|
+
/* Returns the last error code for the database.
|
1304
|
+
*
|
1305
|
+
* @return [Integer] last error code
|
997
1306
|
*/
|
998
1307
|
VALUE Database_errcode(VALUE self) {
|
999
1308
|
Database_t *db = self_to_open_database(self);
|
@@ -1001,10 +1310,9 @@ VALUE Database_errcode(VALUE self) {
|
|
1001
1310
|
return INT2NUM(sqlite3_errcode(db->sqlite3_db));
|
1002
1311
|
}
|
1003
1312
|
|
1004
|
-
/*
|
1005
|
-
*
|
1006
|
-
*
|
1007
|
-
* Returns the last error message for the database.
|
1313
|
+
/* Returns the last error message for the database.
|
1314
|
+
*
|
1315
|
+
* @return [String] last error message
|
1008
1316
|
*/
|
1009
1317
|
VALUE Database_errmsg(VALUE self) {
|
1010
1318
|
Database_t *db = self_to_open_database(self);
|
@@ -1013,10 +1321,10 @@ VALUE Database_errmsg(VALUE self) {
|
|
1013
1321
|
}
|
1014
1322
|
|
1015
1323
|
#ifdef HAVE_SQLITE3_ERROR_OFFSET
|
1016
|
-
/*
|
1017
|
-
*
|
1018
|
-
*
|
1019
|
-
*
|
1324
|
+
/* Returns the offset for the last error. This is useful for indicating where in
|
1325
|
+
* the SQL string an error was encountered.
|
1326
|
+
*
|
1327
|
+
* @return [Integer] offset in the last submitted SQL string
|
1020
1328
|
*/
|
1021
1329
|
VALUE Database_error_offset(VALUE self) {
|
1022
1330
|
Database_t *db = self_to_open_database(self);
|
@@ -1052,14 +1360,24 @@ VALUE Database_gvl_release_threshold_get(VALUE self) {
|
|
1052
1360
|
return INT2NUM(db->gvl_release_threshold);
|
1053
1361
|
}
|
1054
1362
|
|
1055
|
-
/* Sets the database's GVL release threshold.
|
1056
|
-
*
|
1057
|
-
*
|
1058
|
-
*
|
1059
|
-
*
|
1363
|
+
/* Sets the database's GVL release threshold. The release policy changes
|
1364
|
+
* according to the given value:
|
1365
|
+
*
|
1366
|
+
* - Less than 0: the GVL is never released while running queries. This is the
|
1367
|
+
* policy used when a progress handler is set. For more information see
|
1368
|
+
* `#on_progress`.
|
1369
|
+
* - 0: The GVL is released while preparing queries, but held when iterating
|
1370
|
+
* through records.
|
1371
|
+
* - Greater than 0: the GVL is released while preparing queries, and released
|
1372
|
+
* periodically while iterating through records, according to the given
|
1373
|
+
* period. A value of 1 will release the GVL on every iterated record. A value
|
1374
|
+
* of 100 will release the GVL once for every 100 records.
|
1375
|
+
*
|
1376
|
+
* A value of nil sets the threshold to the default value, which is
|
1060
1377
|
* currently 1000.
|
1061
1378
|
*
|
1062
|
-
* @
|
1379
|
+
* @param threshold [Integer, nil] GVL release threshold
|
1380
|
+
* @return [Integer] GVL release threshold
|
1063
1381
|
*/
|
1064
1382
|
VALUE Database_gvl_release_threshold_set(VALUE self, VALUE value) {
|
1065
1383
|
Database_t *db = self_to_open_database(self);
|
@@ -1071,7 +1389,7 @@ VALUE Database_gvl_release_threshold_set(VALUE self, VALUE value) {
|
|
1071
1389
|
if (value_int < -1)
|
1072
1390
|
rb_raise(eArgumentError, "Invalid GVL release threshold value (expect integer >= -1)");
|
1073
1391
|
|
1074
|
-
if (value_int > -1 &&
|
1392
|
+
if (value_int > -1 && db->progress_handler.mode != PROGRESS_NONE)
|
1075
1393
|
Database_reset_progress_handler(self, db);
|
1076
1394
|
db->gvl_release_threshold = value_int;
|
1077
1395
|
break;
|
@@ -1090,87 +1408,104 @@ void Init_ExtraliteDatabase(void) {
|
|
1090
1408
|
VALUE mExtralite = rb_define_module("Extralite");
|
1091
1409
|
rb_define_singleton_method(mExtralite, "runtime_status", Extralite_runtime_status, -1);
|
1092
1410
|
rb_define_singleton_method(mExtralite, "sqlite3_version", Extralite_sqlite3_version, 0);
|
1411
|
+
rb_define_singleton_method(mExtralite, "on_progress", Extralite_on_progress, -1);
|
1093
1412
|
|
1094
1413
|
cDatabase = rb_define_class_under(mExtralite, "Database", rb_cObject);
|
1095
1414
|
rb_define_alloc_func(cDatabase, Database_allocate);
|
1096
1415
|
|
1097
|
-
rb_define_method(cDatabase, "backup",
|
1098
|
-
rb_define_method(cDatabase, "
|
1099
|
-
rb_define_method(cDatabase, "
|
1100
|
-
rb_define_method(cDatabase, "
|
1101
|
-
rb_define_method(cDatabase, "
|
1102
|
-
rb_define_method(cDatabase, "
|
1103
|
-
rb_define_method(cDatabase, "
|
1104
|
-
rb_define_method(cDatabase, "
|
1416
|
+
rb_define_method(cDatabase, "backup", Database_backup, -1);
|
1417
|
+
rb_define_method(cDatabase, "batch_execute", Database_batch_execute, 2);
|
1418
|
+
rb_define_method(cDatabase, "batch_query", Database_batch_query, 2);
|
1419
|
+
rb_define_method(cDatabase, "batch_query_ary", Database_batch_query_ary, 2);
|
1420
|
+
rb_define_method(cDatabase, "batch_query_argv", Database_batch_query_argv, 2);
|
1421
|
+
rb_define_method(cDatabase, "batch_query_hash", Database_batch_query, 2);
|
1422
|
+
rb_define_method(cDatabase, "busy_timeout=", Database_busy_timeout_set, 1);
|
1423
|
+
rb_define_method(cDatabase, "changes", Database_changes, 0);
|
1424
|
+
rb_define_method(cDatabase, "close", Database_close, 0);
|
1425
|
+
rb_define_method(cDatabase, "closed?", Database_closed_p, 0);
|
1426
|
+
rb_define_method(cDatabase, "columns", Database_columns, 1);
|
1427
|
+
rb_define_method(cDatabase, "errcode", Database_errcode, 0);
|
1428
|
+
rb_define_method(cDatabase, "errmsg", Database_errmsg, 0);
|
1105
1429
|
|
1106
1430
|
#ifdef HAVE_SQLITE3_ERROR_OFFSET
|
1107
|
-
rb_define_method(cDatabase, "error_offset",
|
1431
|
+
rb_define_method(cDatabase, "error_offset", Database_error_offset, 0);
|
1108
1432
|
#endif
|
1109
1433
|
|
1110
|
-
rb_define_method(cDatabase, "execute",
|
1111
|
-
rb_define_method(cDatabase, "
|
1112
|
-
rb_define_method(cDatabase, "
|
1113
|
-
rb_define_method(cDatabase, "batch_query_ary", Database_batch_query_ary, 2);
|
1114
|
-
rb_define_method(cDatabase, "batch_query_single_column", Database_batch_query_single_column, 2);
|
1115
|
-
rb_define_method(cDatabase, "filename", Database_filename, -1);
|
1116
|
-
rb_define_method(cDatabase, "gvl_release_threshold", Database_gvl_release_threshold_get, 0);
|
1434
|
+
rb_define_method(cDatabase, "execute", Database_execute, -1);
|
1435
|
+
rb_define_method(cDatabase, "filename", Database_filename, -1);
|
1436
|
+
rb_define_method(cDatabase, "gvl_release_threshold", Database_gvl_release_threshold_get, 0);
|
1117
1437
|
rb_define_method(cDatabase, "gvl_release_threshold=", Database_gvl_release_threshold_set, 1);
|
1118
|
-
rb_define_method(cDatabase, "initialize",
|
1119
|
-
rb_define_method(cDatabase, "inspect",
|
1120
|
-
rb_define_method(cDatabase, "interrupt",
|
1121
|
-
rb_define_method(cDatabase, "last_insert_rowid",
|
1122
|
-
rb_define_method(cDatabase, "limit",
|
1123
|
-
|
1124
|
-
|
1125
|
-
rb_define_method(cDatabase, "
|
1126
|
-
|
1127
|
-
|
1128
|
-
rb_define_method(cDatabase, "
|
1129
|
-
rb_define_method(cDatabase, "
|
1130
|
-
rb_define_method(cDatabase, "
|
1131
|
-
rb_define_method(cDatabase, "
|
1132
|
-
rb_define_method(cDatabase, "
|
1133
|
-
rb_define_method(cDatabase, "
|
1134
|
-
rb_define_method(cDatabase, "
|
1438
|
+
rb_define_method(cDatabase, "initialize", Database_initialize, -1);
|
1439
|
+
rb_define_method(cDatabase, "inspect", Database_inspect, 0);
|
1440
|
+
rb_define_method(cDatabase, "interrupt", Database_interrupt, 0);
|
1441
|
+
rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
|
1442
|
+
rb_define_method(cDatabase, "limit", Database_limit, -1);
|
1443
|
+
|
1444
|
+
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
1445
|
+
rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
|
1446
|
+
#endif
|
1447
|
+
|
1448
|
+
rb_define_method(cDatabase, "on_progress", Database_on_progress, -1);
|
1449
|
+
rb_define_method(cDatabase, "prepare", Database_prepare_hash, -1);
|
1450
|
+
rb_define_method(cDatabase, "prepare_argv", Database_prepare_argv, -1);
|
1451
|
+
rb_define_method(cDatabase, "prepare_ary", Database_prepare_ary, -1);
|
1452
|
+
rb_define_method(cDatabase, "prepare_hash", Database_prepare_hash, -1);
|
1453
|
+
rb_define_method(cDatabase, "query", Database_query, -1);
|
1454
|
+
rb_define_method(cDatabase, "query_argv", Database_query_argv, -1);
|
1455
|
+
rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
|
1456
|
+
rb_define_method(cDatabase, "query_hash", Database_query, -1);
|
1457
|
+
rb_define_method(cDatabase, "query_single", Database_query_single, -1);
|
1458
|
+
rb_define_method(cDatabase, "query_single_ary", Database_query_single_ary, -1);
|
1459
|
+
rb_define_method(cDatabase, "query_single_argv", Database_query_single_argv, -1);
|
1460
|
+
rb_define_method(cDatabase, "query_single_hash", Database_query_single, -1);
|
1461
|
+
rb_define_method(cDatabase, "read_only?", Database_read_only_p, 0);
|
1462
|
+
rb_define_method(cDatabase, "status", Database_status, -1);
|
1463
|
+
rb_define_method(cDatabase, "total_changes", Database_total_changes, 0);
|
1464
|
+
rb_define_method(cDatabase, "trace", Database_trace, 0);
|
1135
1465
|
|
1136
1466
|
#ifdef EXTRALITE_ENABLE_CHANGESET
|
1137
|
-
rb_define_method(cDatabase, "track_changes",
|
1467
|
+
rb_define_method(cDatabase, "track_changes", Database_track_changes, -1);
|
1138
1468
|
#endif
|
1139
1469
|
|
1140
|
-
rb_define_method(cDatabase, "transaction_active?",
|
1141
|
-
|
1142
|
-
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
1143
|
-
rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
|
1144
|
-
#endif
|
1145
|
-
|
1146
|
-
cBlob = rb_define_class_under(mExtralite, "Blob", rb_cString);
|
1470
|
+
rb_define_method(cDatabase, "transaction_active?", Database_transaction_active_p, 0);
|
1147
1471
|
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1472
|
+
cBlob = rb_define_class_under(mExtralite, "Blob", rb_cString);
|
1473
|
+
cError = rb_define_class_under(mExtralite, "Error", rb_eStandardError);
|
1474
|
+
cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
|
1475
|
+
cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
|
1151
1476
|
cInterruptError = rb_define_class_under(mExtralite, "InterruptError", cError);
|
1152
1477
|
cParameterError = rb_define_class_under(mExtralite, "ParameterError", cError);
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
ID_strip
|
1162
|
-
ID_to_s
|
1163
|
-
ID_track
|
1164
|
-
|
1478
|
+
eArgumentError = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
|
1479
|
+
|
1480
|
+
ID_bind = rb_intern("bind");
|
1481
|
+
ID_call = rb_intern("call");
|
1482
|
+
ID_each = rb_intern("each");
|
1483
|
+
ID_keys = rb_intern("keys");
|
1484
|
+
ID_new = rb_intern("new");
|
1485
|
+
ID_pragma = rb_intern("pragma");
|
1486
|
+
ID_strip = rb_intern("strip");
|
1487
|
+
ID_to_s = rb_intern("to_s");
|
1488
|
+
ID_track = rb_intern("track");
|
1489
|
+
|
1490
|
+
SYM_at_least_once = ID2SYM(rb_intern("at_least_once"));
|
1165
1491
|
SYM_gvl_release_threshold = ID2SYM(rb_intern("gvl_release_threshold"));
|
1492
|
+
SYM_once = ID2SYM(rb_intern("once"));
|
1493
|
+
SYM_none = ID2SYM(rb_intern("none"));
|
1494
|
+
SYM_normal = ID2SYM(rb_intern("normal"));
|
1495
|
+
SYM_pragma = ID2SYM(rb_intern("pragma"));
|
1166
1496
|
SYM_read_only = ID2SYM(rb_intern("read_only"));
|
1167
|
-
|
1168
|
-
SYM_wal_journal_mode = ID2SYM(rb_intern("wal_journal_mode"));
|
1497
|
+
SYM_wal = ID2SYM(rb_intern("wal"));
|
1169
1498
|
|
1499
|
+
rb_gc_register_mark_object(SYM_at_least_once);
|
1170
1500
|
rb_gc_register_mark_object(SYM_gvl_release_threshold);
|
1501
|
+
rb_gc_register_mark_object(SYM_once);
|
1502
|
+
rb_gc_register_mark_object(SYM_none);
|
1503
|
+
rb_gc_register_mark_object(SYM_normal);
|
1504
|
+
rb_gc_register_mark_object(SYM_pragma);
|
1171
1505
|
rb_gc_register_mark_object(SYM_read_only);
|
1172
|
-
rb_gc_register_mark_object(
|
1173
|
-
|
1506
|
+
rb_gc_register_mark_object(SYM_wal);
|
1507
|
+
|
1508
|
+
rb_gc_register_mark_object(global_progress_handler.proc);
|
1174
1509
|
|
1175
1510
|
UTF8_ENCODING = rb_utf8_encoding();
|
1176
1511
|
}
|