extralite 2.6 → 2.7
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/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
|
}
|