extralite-bundle 2.6 → 2.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +28 -17
- data/Gemfile +4 -0
- data/Gemfile-bundle +1 -1
- data/README.md +259 -72
- 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 +638 -316
- data/ext/extralite/extconf.rb +7 -11
- data/ext/extralite/extralite.h +89 -48
- data/ext/extralite/iterator.c +6 -83
- data/ext/extralite/query.c +164 -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 +28 -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,73 @@ VALUE Database_load_extension(VALUE self, VALUE path) {
|
|
614
710
|
}
|
615
711
|
#endif
|
616
712
|
|
713
|
+
static inline VALUE Database_prepare(int argc, VALUE *argv, VALUE self, VALUE mode) {
|
714
|
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
715
|
+
|
716
|
+
VALUE args[] = { self, argv[0], mode};
|
717
|
+
VALUE query = rb_funcall_passing_block(cQuery, ID_new, 3, args);
|
718
|
+
if (argc > 1) rb_funcallv(query, ID_bind, argc - 1, argv + 1);
|
719
|
+
RB_GC_GUARD(query);
|
720
|
+
return query;
|
721
|
+
}
|
722
|
+
|
617
723
|
/* call-seq:
|
618
724
|
* db.prepare(sql) -> Extralite::Query
|
619
725
|
* db.prepare(sql, ...) -> Extralite::Query
|
726
|
+
* db.prepare(sql, ...) { ... } -> Extralite::Query
|
620
727
|
*
|
621
|
-
* Creates a prepared
|
622
|
-
* are given, they are bound to the query.
|
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
|
+
* @return [Extralite::Query] prepared query
|
623
734
|
*/
|
624
|
-
VALUE
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
735
|
+
VALUE Database_prepare_hash(int argc, VALUE *argv, VALUE self) {
|
736
|
+
return Database_prepare(argc, argv, self, SYM_hash);
|
737
|
+
}
|
738
|
+
|
739
|
+
/* call-seq:
|
740
|
+
* db.prepare_argv(sql) -> Extralite::Query
|
741
|
+
* db.prepare_argv(sql, ...) -> Extralite::Query
|
742
|
+
* db.prepare_argv(sql, ...) { ... } -> Extralite::Query
|
743
|
+
*
|
744
|
+
* Creates a prepared query with the given SQL query in argv mode. If query
|
745
|
+
* parameters are given, they are bound to the query. If a block is given, it is
|
746
|
+
* used as a transform proc.
|
747
|
+
*
|
748
|
+
* @param sql [String] SQL statement
|
749
|
+
* @return [Extralite::Query] prepared query
|
750
|
+
*/
|
751
|
+
VALUE Database_prepare_argv(int argc, VALUE *argv, VALUE self) {
|
752
|
+
return Database_prepare(argc, argv, self, SYM_argv);
|
630
753
|
}
|
631
754
|
|
632
755
|
/* call-seq:
|
633
|
-
* db.
|
756
|
+
* db.prepare_ary(sql) -> Extralite::Query
|
757
|
+
* db.prepare_ary(sql, ...) -> Extralite::Query
|
758
|
+
* db.prepare_ary(sql, ...) { ... } -> Extralite::Query
|
634
759
|
*
|
635
|
-
*
|
760
|
+
* Creates a prepared query with the given SQL query in ary mode. If query
|
761
|
+
* parameters are given, they are bound to the query. If a block is given, it is
|
762
|
+
* used as a transform proc.
|
763
|
+
*
|
764
|
+
* @param sql [String] SQL statement
|
765
|
+
* @return [Extralite::Query] prepared query
|
766
|
+
*/
|
767
|
+
VALUE Database_prepare_ary(int argc, VALUE *argv, VALUE self) {
|
768
|
+
return Database_prepare(argc, argv, self, SYM_ary);
|
769
|
+
}
|
770
|
+
|
771
|
+
/* Interrupts a long running query. This method is to be called from a different
|
636
772
|
* thread than the one running the query. Upon calling `#interrupt` the running
|
637
773
|
* query will stop and raise an `Extralite::InterruptError` exception.
|
638
774
|
*
|
639
775
|
* It is not safe to call `#interrupt` on a database that is about to be closed.
|
640
|
-
* For more information, consult the [sqlite3 API
|
776
|
+
* For more information, consult the [sqlite3 API
|
777
|
+
* docs](https://sqlite.org/c3ref/interrupt.html).
|
778
|
+
*
|
779
|
+
* @return [Extralite::Database] database
|
641
780
|
*/
|
642
781
|
VALUE Database_interrupt(VALUE self) {
|
643
782
|
Database_t *db = self_to_open_database(self);
|
@@ -711,16 +850,19 @@ VALUE backup_cleanup(VALUE ptr) {
|
|
711
850
|
return Qnil;
|
712
851
|
}
|
713
852
|
|
714
|
-
/*
|
715
|
-
* db.backup(dest) -> db
|
716
|
-
* db.backup(dest) { |remaining, total| } -> db
|
717
|
-
*
|
718
|
-
* Creates a backup of the database to the given destination, which can be
|
853
|
+
/* Creates a backup of the database to the given destination, which can be
|
719
854
|
* either a filename or a database instance. In order to monitor the backup
|
720
855
|
* progress you can pass a block that will be called periodically by the backup
|
721
856
|
* method with two arguments: the remaining page count, and the total page
|
722
857
|
* count, which can be used to display the progress to the user or to collect
|
723
858
|
* statistics.
|
859
|
+
*
|
860
|
+
* db_src.backup(db_dest) do |remaining, total|
|
861
|
+
* puts "Backing up #{remaining}/#{total}"
|
862
|
+
* end
|
863
|
+
*
|
864
|
+
* @param dest [String, Extralite::Database] backup destination
|
865
|
+
* @return [Extralite::Database] source database
|
724
866
|
*/
|
725
867
|
VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
|
726
868
|
VALUE dst;
|
@@ -766,12 +908,17 @@ VALUE Database_backup(int argc, VALUE *argv, VALUE self) {
|
|
766
908
|
return self;
|
767
909
|
}
|
768
910
|
|
769
|
-
/*
|
770
|
-
* Extralite.runtime_status(op[, reset]) -> [value, highwatermark]
|
771
|
-
*
|
772
|
-
* Returns runtime status values for the given op as an array containing the
|
911
|
+
/* Returns runtime status values for the given op as an array containing the
|
773
912
|
* current value and the high water mark value. To reset the high water mark,
|
774
913
|
* pass true as reset.
|
914
|
+
*
|
915
|
+
* @overload runtime_status(op)
|
916
|
+
* @param op [Integer] op
|
917
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
918
|
+
* @overload runtime_status(op, reset)
|
919
|
+
* @param op [Integer] op
|
920
|
+
* @param reset [Integer, bool] reset flag
|
921
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
775
922
|
*/
|
776
923
|
VALUE Extralite_runtime_status(int argc, VALUE* argv, VALUE self) {
|
777
924
|
VALUE op, reset;
|
@@ -785,12 +932,17 @@ VALUE Extralite_runtime_status(int argc, VALUE* argv, VALUE self) {
|
|
785
932
|
return rb_ary_new3(2, LONG2FIX(cur), LONG2FIX(hwm));
|
786
933
|
}
|
787
934
|
|
788
|
-
/*
|
789
|
-
* db.status(op[, reset]) -> [value, highwatermark]
|
790
|
-
*
|
791
|
-
* Returns database status values for the given op as an array containing the
|
935
|
+
/* Returns database status values for the given op as an array containing the
|
792
936
|
* current value and the high water mark value. To reset the high water mark,
|
793
937
|
* pass true as reset.
|
938
|
+
*
|
939
|
+
* @overload status(op)
|
940
|
+
* @param op [Integer] op
|
941
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
942
|
+
* @overload status(op, reset)
|
943
|
+
* @param op [Integer] op
|
944
|
+
* @param reset [Integer, bool] reset flag
|
945
|
+
* @return [Array<Integer>] array containing the value and high water mark
|
794
946
|
*/
|
795
947
|
VALUE Database_status(int argc, VALUE *argv, VALUE self) {
|
796
948
|
VALUE op, reset;
|
@@ -806,12 +958,16 @@ VALUE Database_status(int argc, VALUE *argv, VALUE self) {
|
|
806
958
|
return rb_ary_new3(2, INT2NUM(cur), INT2NUM(hwm));
|
807
959
|
}
|
808
960
|
|
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,
|
961
|
+
/* Returns the current limit for the given category. If a new value is given,
|
814
962
|
* sets the limit to the new value and returns the previous value.
|
963
|
+
*
|
964
|
+
* @overload limit(category)
|
965
|
+
* @param category [Integer] category
|
966
|
+
* @return [Integer] limit value
|
967
|
+
* @overload limit(category, new_value)
|
968
|
+
* @param category [Integer] category
|
969
|
+
* @param new_value [Integer] new value
|
970
|
+
* @return [Integer] old value
|
815
971
|
*/
|
816
972
|
VALUE Database_limit(int argc, VALUE *argv, VALUE self) {
|
817
973
|
VALUE category, new_value;
|
@@ -827,12 +983,18 @@ VALUE Database_limit(int argc, VALUE *argv, VALUE self) {
|
|
827
983
|
return INT2NUM(value);
|
828
984
|
}
|
829
985
|
|
830
|
-
/*
|
831
|
-
*
|
832
|
-
*
|
986
|
+
/* Sets the busy timeout for the database, in seconds or fractions thereof. To
|
987
|
+
* disable the busy timeout, set it to 0 or nil. When the busy timeout is set to
|
988
|
+
* a value larger than zero, running a query when the database is locked will
|
989
|
+
* cause the program to wait for the database to become available. If the
|
990
|
+
* database is still locked when the timeout period has elapsed, the query will
|
991
|
+
* fail with a `Extralite::BusyError` exception.
|
992
|
+
*
|
993
|
+
* Setting the busy timeout allows other threads to run while waiting for the
|
994
|
+
* database to become available. See also `#on_progress`.
|
833
995
|
*
|
834
|
-
*
|
835
|
-
*
|
996
|
+
* @param sec [Number, nil] timeout value
|
997
|
+
* @return [Extralite::Database] database
|
836
998
|
*/
|
837
999
|
VALUE Database_busy_timeout_set(VALUE self, VALUE sec) {
|
838
1000
|
Database_t *db = self_to_open_database(self);
|
@@ -844,10 +1006,9 @@ VALUE Database_busy_timeout_set(VALUE self, VALUE sec) {
|
|
844
1006
|
return self;
|
845
1007
|
}
|
846
1008
|
|
847
|
-
/*
|
848
|
-
*
|
849
|
-
*
|
850
|
-
* Returns the total number of changes made to the database since opening it.
|
1009
|
+
/* Returns the total number of changes made to the database since opening it.
|
1010
|
+
*
|
1011
|
+
* @return [Integer] total changes
|
851
1012
|
*/
|
852
1013
|
VALUE Database_total_changes(VALUE self) {
|
853
1014
|
Database_t *db = self_to_open_database(self);
|
@@ -856,12 +1017,10 @@ VALUE Database_total_changes(VALUE self) {
|
|
856
1017
|
return INT2NUM(value);
|
857
1018
|
}
|
858
1019
|
|
859
|
-
/*
|
860
|
-
*
|
861
|
-
*
|
862
|
-
*
|
863
|
-
* Installs or removes a block that will be invoked for every SQL statement
|
864
|
-
* executed.
|
1020
|
+
/* Installs or removes a block that will be invoked for every SQL statement
|
1021
|
+
* executed. To stop tracing, call `#trace` without a block.
|
1022
|
+
*
|
1023
|
+
* @return [Extralite::Database] database
|
865
1024
|
*/
|
866
1025
|
VALUE Database_trace(VALUE self) {
|
867
1026
|
Database_t *db = self_to_open_database(self);
|
@@ -876,11 +1035,11 @@ VALUE Database_trace(VALUE self) {
|
|
876
1035
|
* or undo the changes. The given table names specify which tables should be
|
877
1036
|
* tracked for changes. Passing a value of nil causes all tables to be tracked.
|
878
1037
|
*
|
879
|
-
*
|
880
|
-
*
|
881
|
-
*
|
1038
|
+
* changeset = db.track_changes(:foo, :bar) do
|
1039
|
+
* perform_a_bunch_of_queries
|
1040
|
+
* end
|
882
1041
|
*
|
883
|
-
*
|
1042
|
+
* File.open('my.changes', 'w+') { |f| f << changeset.to_blob }
|
884
1043
|
*
|
885
1044
|
* @param table [String, Symbol] table to track
|
886
1045
|
* @return [Extralite::Changeset] changeset
|
@@ -899,101 +1058,236 @@ VALUE Database_track_changes(int argc, VALUE *argv, VALUE self) {
|
|
899
1058
|
}
|
900
1059
|
#endif
|
901
1060
|
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
1061
|
+
void Database_reset_progress_handler(VALUE self, Database_t *db) {
|
1062
|
+
db->progress_handler.mode = PROGRESS_NONE;
|
1063
|
+
RB_OBJ_WRITE(self, &db->progress_handler.proc, Qnil);
|
1064
|
+
sqlite3_progress_handler(db->sqlite3_db, 0, NULL, NULL);
|
1065
|
+
sqlite3_busy_handler(db->sqlite3_db, NULL, NULL);
|
906
1066
|
}
|
907
1067
|
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
return
|
1068
|
+
static inline enum progress_handler_mode symbol_to_progress_mode(VALUE mode) {
|
1069
|
+
if (mode == SYM_at_least_once) return PROGRESS_AT_LEAST_ONCE;
|
1070
|
+
if (mode == SYM_once) return PROGRESS_ONCE;
|
1071
|
+
if (mode == SYM_normal) return PROGRESS_NORMAL;
|
1072
|
+
if (mode == SYM_none) return PROGRESS_NONE;
|
1073
|
+
rb_raise(eArgumentError, "Invalid progress handler mode");
|
912
1074
|
}
|
913
1075
|
|
914
|
-
void
|
915
|
-
|
916
|
-
|
917
|
-
|
1076
|
+
inline void Database_issue_query(Database_t *db, VALUE sql) {
|
1077
|
+
if (db->trace_proc != Qnil) rb_funcall(db->trace_proc, ID_call, 1, sql);
|
1078
|
+
switch (db->progress_handler.mode) {
|
1079
|
+
case PROGRESS_AT_LEAST_ONCE:
|
1080
|
+
case PROGRESS_ONCE:
|
1081
|
+
rb_funcall(db->progress_handler.proc, ID_call, 0);
|
1082
|
+
default:
|
1083
|
+
; // do nothing
|
1084
|
+
|
1085
|
+
}
|
918
1086
|
}
|
919
1087
|
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
1088
|
+
struct progress_handler parse_progress_handler_opts(VALUE opts) {
|
1089
|
+
static ID kw_ids[3];
|
1090
|
+
VALUE kw_args[3];
|
1091
|
+
struct progress_handler prog = {
|
1092
|
+
.mode = rb_block_given_p() ? PROGRESS_NORMAL : PROGRESS_NONE,
|
1093
|
+
.proc = rb_block_given_p() ? rb_block_proc() : Qnil,
|
1094
|
+
.period = DEFAULT_PROGRESS_HANDLER_PERIOD,
|
1095
|
+
.tick = DEFAULT_PROGRESS_HANDLER_TICK
|
1096
|
+
};
|
1097
|
+
|
1098
|
+
if (!NIL_P(opts)) {
|
1099
|
+
if (!kw_ids[0]) {
|
1100
|
+
CONST_ID(kw_ids[0], "period");
|
1101
|
+
CONST_ID(kw_ids[1], "tick");
|
1102
|
+
CONST_ID(kw_ids[2], "mode");
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
rb_get_kwargs(opts, kw_ids, 0, 3, kw_args);
|
1106
|
+
if (kw_args[0] != Qundef) { prog.period = NUM2INT(kw_args[0]); }
|
1107
|
+
if (kw_args[1] != Qundef) { prog.tick = NUM2INT(kw_args[1]); }
|
1108
|
+
if (kw_args[2] != Qundef) { prog.mode = symbol_to_progress_mode(kw_args[2]); }
|
1109
|
+
if (prog.tick > prog.period) prog.tick = prog.period;
|
1110
|
+
}
|
1111
|
+
if (NIL_P(prog.proc) || (prog.period <= 0)) prog.mode = PROGRESS_NONE;
|
1112
|
+
if (prog.mode == PROGRESS_NONE) prog.proc = Qnil;
|
1113
|
+
|
1114
|
+
return prog;
|
1115
|
+
}
|
1116
|
+
|
1117
|
+
/* Installs or removes a progress handler that will be executed periodically
|
925
1118
|
* while a query is running. This method can be used to support switching
|
926
1119
|
* between fibers and threads or implementing timeouts for running queries.
|
927
1120
|
*
|
928
|
-
* The
|
929
|
-
* machine instructions that are evaluated between successive
|
930
|
-
* progress handler. A period of less than 1 removes the
|
1121
|
+
* The `period` parameter specifies the approximate number of SQLite
|
1122
|
+
* virtual machine instructions that are evaluated between successive
|
1123
|
+
* invocations of the progress handler. A period of less than 1 removes the
|
1124
|
+
* progress handler. The default period value is 1000.
|
1125
|
+
*
|
1126
|
+
* The optional `tick` parameter specifies the granularity of how often the
|
1127
|
+
* progress handler is called. The default tick value is 10, which means that
|
1128
|
+
* Extralite's underlying progress callback will be called every 10 SQLite VM
|
1129
|
+
* instructions. The given progress proc, however, will be only called every
|
1130
|
+
* `period` (cumulative) VM instructions. This allows the progress handler to
|
1131
|
+
* work correctly also when running simple queries that don't include many
|
1132
|
+
* VM instructions. If the `tick` value is greater than the period value it is
|
1133
|
+
* automatically capped to the period value.
|
1134
|
+
*
|
1135
|
+
* The `mode` parameter controls the progress handler mode, which is one of the
|
1136
|
+
* following:
|
1137
|
+
*
|
1138
|
+
* - `:normal` (default): the progress handler proc is invoked on query
|
1139
|
+
* progress.
|
1140
|
+
* - `:once`: the progress handler proc is invoked only once, when preparing the
|
1141
|
+
* query.
|
1142
|
+
* - `:at_least_once`: the progress handler proc is invoked when prearing the
|
1143
|
+
* query, and on query progress.
|
931
1144
|
*
|
932
1145
|
* The progress handler is called also when the database is busy. This lets the
|
933
1146
|
* application perform work while waiting for the database to become unlocked,
|
934
1147
|
* or implement a timeout. Note that setting the database's busy_timeout _after_
|
935
1148
|
* setting a progress handler may lead to undefined behaviour in a concurrent
|
936
|
-
* application.
|
1149
|
+
* application. When busy, the progress handler proc is passed `true` as the
|
1150
|
+
* first argument.
|
937
1151
|
*
|
938
1152
|
* When the progress handler is set, the gvl release threshold value is set to
|
939
1153
|
* -1, which means that the GVL will not be released at all when preparing or
|
940
1154
|
* running queries. It is the application's responsibility to let other threads
|
941
1155
|
* or fibers run by calling e.g. Thread.pass:
|
942
|
-
*
|
943
|
-
* db.on_progress
|
1156
|
+
*
|
1157
|
+
* db.on_progress do
|
944
1158
|
* do_something_interesting
|
945
1159
|
* Thread.pass # let other threads run
|
946
1160
|
* end
|
947
|
-
*
|
948
|
-
* Note that the progress handler is set globally for the database and that
|
1161
|
+
*
|
1162
|
+
* Note that the progress handler is set globally for the database and that
|
949
1163
|
* 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
|
-
*
|
1164
|
+
* running or at what time they were started. This means that you'll need to
|
1165
|
+
* wrap the stock #query_xxx and #execute methods with your own code that
|
952
1166
|
* calculates timeouts, for example:
|
953
|
-
*
|
1167
|
+
*
|
954
1168
|
* def setup_progress_handler
|
955
|
-
* @db.on_progress
|
1169
|
+
* @db.on_progress do
|
956
1170
|
* raise TimeoutError if Time.now - @t0 >= @timeout
|
957
1171
|
* Thread.pass
|
958
1172
|
* end
|
959
1173
|
* end
|
960
|
-
*
|
1174
|
+
*
|
961
1175
|
* def query(sql, *)
|
962
1176
|
* @t0 = Time.now
|
963
1177
|
* @db.query(sql, *)
|
964
1178
|
* end
|
965
|
-
*
|
1179
|
+
*
|
966
1180
|
* If the gvl release threshold is set to a value equal to or larger than 0
|
967
1181
|
* after setting the progress handler, the progress handler will be reset.
|
968
1182
|
*
|
969
1183
|
* @param period [Integer] progress handler period
|
1184
|
+
* @param [Hash] opts progress options
|
1185
|
+
* @option opts [Integer] :period period value (`1000` by default)
|
1186
|
+
* @option opts [Integer] :tick tick value (`10` by default)
|
1187
|
+
* @option opts [Symbol] :mode progress handler mode (`:normal` by default)
|
970
1188
|
* @returns [Extralite::Database] database
|
971
1189
|
*/
|
972
|
-
VALUE Database_on_progress(VALUE
|
1190
|
+
VALUE Database_on_progress(int argc, VALUE *argv, VALUE self) {
|
973
1191
|
Database_t *db = self_to_open_database(self);
|
974
|
-
|
1192
|
+
VALUE opts;
|
1193
|
+
struct progress_handler prog;
|
975
1194
|
|
976
|
-
|
977
|
-
|
978
|
-
db->gvl_release_threshold = -1;
|
1195
|
+
rb_scan_args(argc, argv, "00:", &opts);
|
1196
|
+
prog = parse_progress_handler_opts(opts);
|
979
1197
|
|
980
|
-
|
981
|
-
|
982
|
-
}
|
983
|
-
else {
|
984
|
-
RB_OBJ_WRITE(self, &db->progress_handler_proc, Qnil);
|
1198
|
+
if (prog.mode == PROGRESS_NONE) {
|
1199
|
+
Database_reset_progress_handler(self, db);
|
985
1200
|
db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD;
|
986
|
-
|
987
|
-
sqlite3_busy_handler(db->sqlite3_db, NULL, NULL);
|
1201
|
+
return self;
|
988
1202
|
}
|
989
1203
|
|
1204
|
+
db->gvl_release_threshold = -1;
|
1205
|
+
db->progress_handler.mode = prog.mode;
|
1206
|
+
RB_OBJ_WRITE(self, &db->progress_handler.proc, prog.proc);
|
1207
|
+
db->progress_handler.period = prog.period;
|
1208
|
+
db->progress_handler.tick = prog.tick;
|
1209
|
+
db->progress_handler.tick_count = 0;
|
1210
|
+
db->progress_handler.call_count = 0;
|
1211
|
+
|
1212
|
+
// The PROGRESS_ONCE mode works by invoking the progress handler proc exactly
|
1213
|
+
// once, before iterating over the result set, so in that mode we don't
|
1214
|
+
// actually need to set the progress handler at the sqlite level.
|
1215
|
+
if (prog.mode != PROGRESS_ONCE)
|
1216
|
+
sqlite3_progress_handler(db->sqlite3_db, prog.tick, &Database_progress_handler, db);
|
1217
|
+
if (prog.mode != PROGRESS_NONE)
|
1218
|
+
sqlite3_busy_handler(db->sqlite3_db, &Database_busy_handler, db);
|
1219
|
+
|
990
1220
|
return self;
|
991
1221
|
}
|
992
1222
|
|
993
|
-
/*
|
994
|
-
*
|
1223
|
+
/* Installs or removes a global progress handler that will be executed
|
1224
|
+
* periodically while a query is running. This method can be used to support
|
1225
|
+
* switching between fibers and threads or implementing timeouts for running
|
1226
|
+
* queries.
|
1227
|
+
*
|
1228
|
+
* This method sets the progress handler settings and behaviour for all
|
1229
|
+
* subsequently created `Database` instances. Calling this method will have no
|
1230
|
+
* effect on already existing `Database` instances
|
1231
|
+
*
|
1232
|
+
* The `period` parameter specifies the approximate number of SQLite
|
1233
|
+
* virtual machine instructions that are evaluated between successive
|
1234
|
+
* invocations of the progress handler. A period of less than 1 removes the
|
1235
|
+
* progress handler. The default period value is 1000.
|
1236
|
+
*
|
1237
|
+
* The optional `tick` parameter specifies the granularity of how often the
|
1238
|
+
* progress handler is called. The default tick value is 10, which means that
|
1239
|
+
* Extralite's underlying progress callback will be called every 10 SQLite VM
|
1240
|
+
* instructions. The given progress proc, however, will be only called every
|
1241
|
+
* `period` (cumulative) VM instructions. This allows the progress handler to
|
1242
|
+
* work correctly also when running simple queries that don't include many
|
1243
|
+
* VM instructions. If the `tick` value is greater than the period value it is
|
1244
|
+
* automatically capped to the period value.
|
1245
|
+
*
|
1246
|
+
* The `mode` parameter controls the progress handler mode, which is one of the
|
1247
|
+
* following:
|
1248
|
+
*
|
1249
|
+
* - `:normal` (default): the progress handler proc is invoked on query
|
1250
|
+
* progress.
|
1251
|
+
* - `:once`: the progress handler proc is invoked only once, when preparing the
|
1252
|
+
* query.
|
1253
|
+
* - `:at_least_once`: the progress handler proc is invoked when prearing the
|
1254
|
+
* query, and on query progress.
|
1255
|
+
*
|
1256
|
+
* The progress handler is called also when the database is busy. This lets the
|
1257
|
+
* application perform work while waiting for the database to become unlocked,
|
1258
|
+
* or implement a timeout. Note that setting the database's busy_timeout _after_
|
1259
|
+
* setting a progress handler may lead to undefined behaviour in a concurrent
|
1260
|
+
* application. When busy, the progress handler proc is passed `true` as the
|
1261
|
+
* first argument.
|
1262
|
+
*
|
1263
|
+
* When the progress handler is set, the gvl release threshold value is set to
|
1264
|
+
* -1, which means that the GVL will not be released at all when preparing or
|
1265
|
+
* running queries. It is the application's responsibility to let other threads
|
1266
|
+
* or fibers run by calling e.g. Thread.pass:
|
1267
|
+
*
|
1268
|
+
* Extralite.on_progress do
|
1269
|
+
* do_something_interesting
|
1270
|
+
* Thread.pass # let other threads run
|
1271
|
+
* end
|
995
1272
|
*
|
996
|
-
*
|
1273
|
+
* @param period [Integer] progress handler period
|
1274
|
+
* @param [Hash] opts progress options
|
1275
|
+
* @option opts [Integer] :period period value (`1000` by default)
|
1276
|
+
* @option opts [Integer] :tick tick value (`10` by default)
|
1277
|
+
* @option opts [Symbol] :mode progress handler mode (`:normal` by default)
|
1278
|
+
* @returns [Extralite::Database] database
|
1279
|
+
*/
|
1280
|
+
VALUE Extralite_on_progress(int argc, VALUE *argv, VALUE self) {
|
1281
|
+
VALUE opts;
|
1282
|
+
|
1283
|
+
rb_scan_args(argc, argv, "00:", &opts);
|
1284
|
+
global_progress_handler = parse_progress_handler_opts(opts);
|
1285
|
+
return self;
|
1286
|
+
}
|
1287
|
+
|
1288
|
+
/* Returns the last error code for the database.
|
1289
|
+
*
|
1290
|
+
* @return [Integer] last error code
|
997
1291
|
*/
|
998
1292
|
VALUE Database_errcode(VALUE self) {
|
999
1293
|
Database_t *db = self_to_open_database(self);
|
@@ -1001,10 +1295,9 @@ VALUE Database_errcode(VALUE self) {
|
|
1001
1295
|
return INT2NUM(sqlite3_errcode(db->sqlite3_db));
|
1002
1296
|
}
|
1003
1297
|
|
1004
|
-
/*
|
1005
|
-
*
|
1006
|
-
*
|
1007
|
-
* Returns the last error message for the database.
|
1298
|
+
/* Returns the last error message for the database.
|
1299
|
+
*
|
1300
|
+
* @return [String] last error message
|
1008
1301
|
*/
|
1009
1302
|
VALUE Database_errmsg(VALUE self) {
|
1010
1303
|
Database_t *db = self_to_open_database(self);
|
@@ -1013,10 +1306,10 @@ VALUE Database_errmsg(VALUE self) {
|
|
1013
1306
|
}
|
1014
1307
|
|
1015
1308
|
#ifdef HAVE_SQLITE3_ERROR_OFFSET
|
1016
|
-
/*
|
1017
|
-
*
|
1018
|
-
*
|
1019
|
-
*
|
1309
|
+
/* Returns the offset for the last error. This is useful for indicating where in
|
1310
|
+
* the SQL string an error was encountered.
|
1311
|
+
*
|
1312
|
+
* @return [Integer] offset in the last submitted SQL string
|
1020
1313
|
*/
|
1021
1314
|
VALUE Database_error_offset(VALUE self) {
|
1022
1315
|
Database_t *db = self_to_open_database(self);
|
@@ -1052,14 +1345,24 @@ VALUE Database_gvl_release_threshold_get(VALUE self) {
|
|
1052
1345
|
return INT2NUM(db->gvl_release_threshold);
|
1053
1346
|
}
|
1054
1347
|
|
1055
|
-
/* Sets the database's GVL release threshold.
|
1056
|
-
*
|
1057
|
-
*
|
1058
|
-
*
|
1059
|
-
*
|
1348
|
+
/* Sets the database's GVL release threshold. The release policy changes
|
1349
|
+
* according to the given value:
|
1350
|
+
*
|
1351
|
+
* - Less than 0: the GVL is never released while running queries. This is the
|
1352
|
+
* policy used when a progress handler is set. For more information see
|
1353
|
+
* `#on_progress`.
|
1354
|
+
* - 0: The GVL is released while preparing queries, but held when iterating
|
1355
|
+
* through records.
|
1356
|
+
* - Greater than 0: the GVL is released while preparing queries, and released
|
1357
|
+
* periodically while iterating through records, according to the given
|
1358
|
+
* period. A value of 1 will release the GVL on every iterated record. A value
|
1359
|
+
* of 100 will release the GVL once for every 100 records.
|
1360
|
+
*
|
1361
|
+
* A value of nil sets the threshold to the default value, which is
|
1060
1362
|
* currently 1000.
|
1061
1363
|
*
|
1062
|
-
* @
|
1364
|
+
* @param [Integer, nil] GVL release threshold
|
1365
|
+
* @return [Integer] GVL release threshold
|
1063
1366
|
*/
|
1064
1367
|
VALUE Database_gvl_release_threshold_set(VALUE self, VALUE value) {
|
1065
1368
|
Database_t *db = self_to_open_database(self);
|
@@ -1071,7 +1374,7 @@ VALUE Database_gvl_release_threshold_set(VALUE self, VALUE value) {
|
|
1071
1374
|
if (value_int < -1)
|
1072
1375
|
rb_raise(eArgumentError, "Invalid GVL release threshold value (expect integer >= -1)");
|
1073
1376
|
|
1074
|
-
if (value_int > -1 &&
|
1377
|
+
if (value_int > -1 && db->progress_handler.mode != PROGRESS_NONE)
|
1075
1378
|
Database_reset_progress_handler(self, db);
|
1076
1379
|
db->gvl_release_threshold = value_int;
|
1077
1380
|
break;
|
@@ -1090,87 +1393,106 @@ void Init_ExtraliteDatabase(void) {
|
|
1090
1393
|
VALUE mExtralite = rb_define_module("Extralite");
|
1091
1394
|
rb_define_singleton_method(mExtralite, "runtime_status", Extralite_runtime_status, -1);
|
1092
1395
|
rb_define_singleton_method(mExtralite, "sqlite3_version", Extralite_sqlite3_version, 0);
|
1396
|
+
rb_define_singleton_method(mExtralite, "on_progress", Extralite_on_progress, -1);
|
1093
1397
|
|
1094
1398
|
cDatabase = rb_define_class_under(mExtralite, "Database", rb_cObject);
|
1095
1399
|
rb_define_alloc_func(cDatabase, Database_allocate);
|
1096
1400
|
|
1097
|
-
rb_define_method(cDatabase,
|
1098
|
-
|
1099
|
-
|
1100
|
-
|
1101
|
-
|
1102
|
-
|
1103
|
-
|
1104
|
-
|
1401
|
+
#define DEF(s, f, a) rb_define_method(cDatabase, s, f, a)
|
1402
|
+
|
1403
|
+
DEF("backup", Database_backup, -1);
|
1404
|
+
DEF("batch_execute", Database_batch_execute, 2);
|
1405
|
+
DEF("batch_query", Database_batch_query, 2);
|
1406
|
+
DEF("batch_query_ary", Database_batch_query_ary, 2);
|
1407
|
+
DEF("batch_query_argv", Database_batch_query_argv, 2);
|
1408
|
+
DEF("batch_query_hash", Database_batch_query, 2);
|
1409
|
+
DEF("busy_timeout=", Database_busy_timeout_set, 1);
|
1410
|
+
DEF("changes", Database_changes, 0);
|
1411
|
+
DEF("close", Database_close, 0);
|
1412
|
+
DEF("closed?", Database_closed_p, 0);
|
1413
|
+
DEF("columns", Database_columns, 1);
|
1414
|
+
DEF("errcode", Database_errcode, 0);
|
1415
|
+
DEF("errmsg", Database_errmsg, 0);
|
1105
1416
|
|
1106
1417
|
#ifdef HAVE_SQLITE3_ERROR_OFFSET
|
1107
|
-
|
1418
|
+
DEF("error_offset", Database_error_offset, 0);
|
1108
1419
|
#endif
|
1109
1420
|
|
1110
|
-
|
1111
|
-
|
1112
|
-
|
1113
|
-
|
1114
|
-
|
1115
|
-
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
|
1127
|
-
|
1128
|
-
|
1129
|
-
|
1130
|
-
|
1131
|
-
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1421
|
+
DEF("execute", Database_execute, -1);
|
1422
|
+
DEF("filename", Database_filename, -1);
|
1423
|
+
DEF("gvl_release_threshold", Database_gvl_release_threshold_get, 0);
|
1424
|
+
DEF("gvl_release_threshold=", Database_gvl_release_threshold_set, 1);
|
1425
|
+
DEF("initialize", Database_initialize, -1);
|
1426
|
+
DEF("inspect", Database_inspect, 0);
|
1427
|
+
DEF("interrupt", Database_interrupt, 0);
|
1428
|
+
DEF("last_insert_rowid", Database_last_insert_rowid, 0);
|
1429
|
+
DEF("limit", Database_limit, -1);
|
1430
|
+
|
1431
|
+
#ifdef HAVE_SQLITE3_LOAD_EXTENSION
|
1432
|
+
DEF("load_extension", Database_load_extension, 1);
|
1433
|
+
#endif
|
1434
|
+
|
1435
|
+
DEF("on_progress", Database_on_progress, -1);
|
1436
|
+
DEF("prepare", Database_prepare_hash, -1);
|
1437
|
+
DEF("prepare_argv", Database_prepare_argv, -1);
|
1438
|
+
DEF("prepare_ary", Database_prepare_ary, -1);
|
1439
|
+
DEF("prepare_hash", Database_prepare_hash, -1);
|
1440
|
+
DEF("query", Database_query, -1);
|
1441
|
+
DEF("query_argv", Database_query_argv, -1);
|
1442
|
+
DEF("query_ary", Database_query_ary, -1);
|
1443
|
+
DEF("query_hash", Database_query, -1);
|
1444
|
+
DEF("query_single", Database_query_single, -1);
|
1445
|
+
DEF("query_single_ary", Database_query_single_ary, -1);
|
1446
|
+
DEF("query_single_argv", Database_query_single_argv, -1);
|
1447
|
+
DEF("query_single_hash", Database_query_single, -1);
|
1448
|
+
DEF("read_only?", Database_read_only_p, 0);
|
1449
|
+
DEF("status", Database_status, -1);
|
1450
|
+
DEF("total_changes", Database_total_changes, 0);
|
1451
|
+
DEF("trace", Database_trace, 0);
|
1135
1452
|
|
1136
1453
|
#ifdef EXTRALITE_ENABLE_CHANGESET
|
1137
|
-
|
1454
|
+
DEF("track_changes", Database_track_changes, -1);
|
1138
1455
|
#endif
|
1139
1456
|
|
1140
|
-
|
1457
|
+
DEF("transaction_active?", Database_transaction_active_p, 0);
|
1141
1458
|
|
1142
|
-
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
cBlob = rb_define_class_under(mExtralite, "Blob", rb_cString);
|
1147
|
-
|
1148
|
-
cError = rb_define_class_under(mExtralite, "Error", rb_eStandardError);
|
1149
|
-
cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
|
1150
|
-
cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
|
1459
|
+
cBlob = rb_define_class_under(mExtralite, "Blob", rb_cString);
|
1460
|
+
cError = rb_define_class_under(mExtralite, "Error", rb_eStandardError);
|
1461
|
+
cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
|
1462
|
+
cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
|
1151
1463
|
cInterruptError = rb_define_class_under(mExtralite, "InterruptError", cError);
|
1152
1464
|
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
|
-
|
1465
|
+
eArgumentError = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
|
1466
|
+
|
1467
|
+
ID_bind = rb_intern("bind");
|
1468
|
+
ID_call = rb_intern("call");
|
1469
|
+
ID_each = rb_intern("each");
|
1470
|
+
ID_keys = rb_intern("keys");
|
1471
|
+
ID_new = rb_intern("new");
|
1472
|
+
ID_pragma = rb_intern("pragma");
|
1473
|
+
ID_strip = rb_intern("strip");
|
1474
|
+
ID_to_s = rb_intern("to_s");
|
1475
|
+
ID_track = rb_intern("track");
|
1476
|
+
|
1477
|
+
SYM_at_least_once = ID2SYM(rb_intern("at_least_once"));
|
1165
1478
|
SYM_gvl_release_threshold = ID2SYM(rb_intern("gvl_release_threshold"));
|
1479
|
+
SYM_once = ID2SYM(rb_intern("once"));
|
1480
|
+
SYM_none = ID2SYM(rb_intern("none"));
|
1481
|
+
SYM_normal = ID2SYM(rb_intern("normal"));
|
1482
|
+
SYM_pragma = ID2SYM(rb_intern("pragma"));
|
1166
1483
|
SYM_read_only = ID2SYM(rb_intern("read_only"));
|
1167
|
-
|
1168
|
-
SYM_wal_journal_mode = ID2SYM(rb_intern("wal_journal_mode"));
|
1484
|
+
SYM_wal = ID2SYM(rb_intern("wal"));
|
1169
1485
|
|
1486
|
+
rb_gc_register_mark_object(SYM_at_least_once);
|
1170
1487
|
rb_gc_register_mark_object(SYM_gvl_release_threshold);
|
1488
|
+
rb_gc_register_mark_object(SYM_once);
|
1489
|
+
rb_gc_register_mark_object(SYM_none);
|
1490
|
+
rb_gc_register_mark_object(SYM_normal);
|
1491
|
+
rb_gc_register_mark_object(SYM_pragma);
|
1171
1492
|
rb_gc_register_mark_object(SYM_read_only);
|
1172
|
-
rb_gc_register_mark_object(
|
1173
|
-
|
1493
|
+
rb_gc_register_mark_object(SYM_wal);
|
1494
|
+
|
1495
|
+
rb_gc_register_mark_object(global_progress_handler.proc);
|
1174
1496
|
|
1175
1497
|
UTF8_ENCODING = rb_utf8_encoding();
|
1176
1498
|
}
|