extralite 1.4 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +3 -8
- data/CHANGELOG.md +18 -0
- data/Gemfile.lock +12 -33
- data/README.md +83 -20
- data/Rakefile +17 -8
- data/ext/extralite/extralite.c +239 -26
- data/extralite.gemspec +5 -5
- data/lib/extralite/version.rb +1 -1
- data/lib/extralite.rb +20 -0
- data/lib/sequel/adapters/extralite.rb +380 -0
- data/test/perf.rb +51 -0
- data/test/run.rb +5 -0
- data/test/test_database.rb +108 -3
- data/test/test_sequel.rb +24 -0
- metadata +16 -13
data/ext/extralite/extralite.c
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
#include <stdio.h>
|
2
2
|
#include "ruby.h"
|
3
|
+
#include "ruby/thread.h"
|
3
4
|
#include <sqlite3.h>
|
4
5
|
|
5
6
|
VALUE cError;
|
6
7
|
VALUE cSQLError;
|
7
8
|
VALUE cBusyError;
|
9
|
+
|
10
|
+
ID ID_KEYS;
|
8
11
|
ID ID_STRIP;
|
12
|
+
ID ID_TO_S;
|
9
13
|
|
10
14
|
typedef struct Database_t {
|
11
15
|
sqlite3 *sqlite3_db;
|
@@ -47,6 +51,10 @@ static VALUE Database_allocate(VALUE klass) {
|
|
47
51
|
} \
|
48
52
|
}
|
49
53
|
|
54
|
+
/* call-seq: initialize(path)
|
55
|
+
*
|
56
|
+
* Initializes a new SQLite database with the given path.
|
57
|
+
*/
|
50
58
|
|
51
59
|
VALUE Database_initialize(VALUE self, VALUE path) {
|
52
60
|
int rc;
|
@@ -68,6 +76,10 @@ VALUE Database_initialize(VALUE self, VALUE path) {
|
|
68
76
|
return Qnil;
|
69
77
|
}
|
70
78
|
|
79
|
+
/* call-seq: close
|
80
|
+
*
|
81
|
+
* Closes the database.
|
82
|
+
*/
|
71
83
|
VALUE Database_close(VALUE self) {
|
72
84
|
int rc;
|
73
85
|
Database_t *db;
|
@@ -82,6 +94,10 @@ VALUE Database_close(VALUE self) {
|
|
82
94
|
return self;
|
83
95
|
}
|
84
96
|
|
97
|
+
/* call-seq: closed?
|
98
|
+
*
|
99
|
+
* Returns true if the database is closed.
|
100
|
+
*/
|
85
101
|
VALUE Database_closed_p(VALUE self) {
|
86
102
|
Database_t *db;
|
87
103
|
GetDatabase(self, db);
|
@@ -108,8 +124,35 @@ inline VALUE get_column_value(sqlite3_stmt *stmt, int col, int type) {
|
|
108
124
|
return Qnil;
|
109
125
|
}
|
110
126
|
|
127
|
+
static void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value);
|
128
|
+
|
129
|
+
static inline void bind_hash_parameter_values(sqlite3_stmt *stmt, VALUE hash) {
|
130
|
+
VALUE keys = rb_funcall(hash, ID_KEYS, 0);
|
131
|
+
int len = RARRAY_LEN(keys);
|
132
|
+
for (int i = 0; i < len; i++) {
|
133
|
+
VALUE k = RARRAY_AREF(keys, i);
|
134
|
+
VALUE v = rb_hash_aref(hash, k);
|
135
|
+
|
136
|
+
switch (TYPE(k)) {
|
137
|
+
case T_FIXNUM:
|
138
|
+
bind_parameter_value(stmt, NUM2INT(k), v);
|
139
|
+
return;
|
140
|
+
case T_SYMBOL:
|
141
|
+
k = rb_funcall(k, ID_TO_S, 0);
|
142
|
+
case T_STRING:
|
143
|
+
if(RSTRING_PTR(k)[0] != ':') k = rb_str_plus(rb_str_new2(":"), k);
|
144
|
+
int pos = sqlite3_bind_parameter_index(stmt, StringValuePtr(k));
|
145
|
+
bind_parameter_value(stmt, pos, v);
|
146
|
+
return;
|
147
|
+
default:
|
148
|
+
rb_raise(cError, "Cannot bind hash key value idx %d", i);
|
149
|
+
}
|
150
|
+
}
|
151
|
+
RB_GC_GUARD(keys);
|
152
|
+
}
|
153
|
+
|
111
154
|
static inline void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value) {
|
112
|
-
switch (TYPE(value)) {
|
155
|
+
switch (TYPE(value)) {
|
113
156
|
case T_NIL:
|
114
157
|
sqlite3_bind_null(stmt, pos);
|
115
158
|
return;
|
@@ -128,6 +171,9 @@ static inline void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value
|
|
128
171
|
case T_STRING:
|
129
172
|
sqlite3_bind_text(stmt, pos, RSTRING_PTR(value), RSTRING_LEN(value), SQLITE_TRANSIENT);
|
130
173
|
return;
|
174
|
+
case T_HASH:
|
175
|
+
bind_hash_parameter_values(stmt, value);
|
176
|
+
return;
|
131
177
|
default:
|
132
178
|
rb_raise(cError, "Cannot bind parameter at position %d", pos);
|
133
179
|
}
|
@@ -143,7 +189,7 @@ static inline void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv
|
|
143
189
|
|
144
190
|
static inline VALUE get_column_names(sqlite3_stmt *stmt, int column_count) {
|
145
191
|
VALUE arr = rb_ary_new2(column_count);
|
146
|
-
for (int i = 0; i < column_count; i++) {
|
192
|
+
for (int i = 0; i < column_count; i++) {
|
147
193
|
VALUE name = ID2SYM(rb_intern(sqlite3_column_name(stmt, i)));
|
148
194
|
rb_ary_push(arr, name);
|
149
195
|
}
|
@@ -168,36 +214,80 @@ static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
|
|
168
214
|
return row;
|
169
215
|
}
|
170
216
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
const char *
|
217
|
+
struct multi_stmt_ctx {
|
218
|
+
sqlite3 *db;
|
219
|
+
sqlite3_stmt **stmt;
|
220
|
+
const char *str;
|
221
|
+
int len;
|
222
|
+
int rc;
|
223
|
+
};
|
224
|
+
|
225
|
+
void *prepare_multi_stmt_without_gvl(void *ptr) {
|
226
|
+
struct multi_stmt_ctx *ctx = (struct multi_stmt_ctx *)ptr;
|
227
|
+
const char *rest = NULL;
|
228
|
+
const char *str = ctx->str;
|
229
|
+
const char *end = ctx->str + ctx->len;
|
175
230
|
while (1) {
|
176
|
-
|
177
|
-
if (rc) {
|
178
|
-
sqlite3_finalize(*stmt);
|
179
|
-
|
231
|
+
ctx->rc = sqlite3_prepare_v2(ctx->db, str, end - str, ctx->stmt, &rest);
|
232
|
+
if (ctx->rc) {
|
233
|
+
sqlite3_finalize(*ctx->stmt);
|
234
|
+
return NULL;
|
180
235
|
}
|
181
236
|
|
182
|
-
if (rest == end) return;
|
183
|
-
|
237
|
+
if (rest == end) return NULL;
|
238
|
+
|
184
239
|
// perform current query, but discard its results
|
185
|
-
rc = sqlite3_step(*stmt);
|
186
|
-
sqlite3_finalize(*stmt);
|
187
|
-
switch (rc) {
|
240
|
+
ctx->rc = sqlite3_step(*ctx->stmt);
|
241
|
+
sqlite3_finalize(*ctx->stmt);
|
242
|
+
switch (ctx->rc) {
|
188
243
|
case SQLITE_BUSY:
|
189
|
-
rb_raise(cBusyError, "Database is busy");
|
190
244
|
case SQLITE_ERROR:
|
191
|
-
|
245
|
+
case SQLITE_MISUSE:
|
246
|
+
return NULL;
|
192
247
|
}
|
193
|
-
|
248
|
+
str = rest;
|
194
249
|
}
|
250
|
+
return NULL;
|
195
251
|
}
|
196
252
|
|
197
|
-
|
253
|
+
/*
|
254
|
+
This function prepares a statement from an SQL string containing one or more SQL
|
255
|
+
statements. It will release the GVL while the statements are being prepared and
|
256
|
+
executed. All statements excluding the last one are executed. The last statement
|
257
|
+
is not executed, but instead handed back to the caller for looping over results.
|
258
|
+
*/
|
259
|
+
inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
|
260
|
+
struct multi_stmt_ctx ctx = {db, stmt, RSTRING_PTR(sql), RSTRING_LEN(sql), 0};
|
261
|
+
rb_thread_call_without_gvl(prepare_multi_stmt_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
|
262
|
+
RB_GC_GUARD(sql);
|
263
|
+
|
264
|
+
switch (ctx.rc) {
|
265
|
+
case 0:
|
266
|
+
return;
|
267
|
+
case SQLITE_BUSY:
|
268
|
+
rb_raise(cBusyError, "Database is busy");
|
269
|
+
case SQLITE_ERROR:
|
270
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
|
271
|
+
default:
|
272
|
+
rb_raise(cError, "Invalid return code for prepare_multi_stmt_without_gvl: %d (please open an issue on https://github.com/digital-fabric/extralite)", ctx.rc);
|
273
|
+
}
|
274
|
+
}
|
275
|
+
|
276
|
+
struct step_ctx {
|
277
|
+
sqlite3_stmt *stmt;
|
198
278
|
int rc;
|
199
|
-
|
200
|
-
|
279
|
+
};
|
280
|
+
|
281
|
+
void *stmt_iterate_without_gvl(void *ptr) {
|
282
|
+
struct step_ctx *ctx = (struct step_ctx *)ptr;
|
283
|
+
ctx->rc = sqlite3_step(ctx->stmt);
|
284
|
+
return NULL;
|
285
|
+
}
|
286
|
+
|
287
|
+
inline int stmt_iterate(sqlite3_stmt *stmt, sqlite3 *db) {
|
288
|
+
struct step_ctx ctx = {stmt, 0};
|
289
|
+
rb_thread_call_without_gvl(stmt_iterate_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
|
290
|
+
switch (ctx.rc) {
|
201
291
|
case SQLITE_ROW:
|
202
292
|
return 1;
|
203
293
|
case SQLITE_DONE:
|
@@ -207,7 +297,7 @@ inline int stmt_iterate(sqlite3_stmt *stmt, sqlite3 *db) {
|
|
207
297
|
case SQLITE_ERROR:
|
208
298
|
rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
|
209
299
|
default:
|
210
|
-
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
300
|
+
rb_raise(cError, "Invalid return code for sqlite3_step: %d (please open an issue on https://github.com/digital-fabric/extralite)", ctx.rc);
|
211
301
|
}
|
212
302
|
|
213
303
|
return 0;
|
@@ -264,6 +354,29 @@ VALUE safe_query_hash(VALUE arg) {
|
|
264
354
|
return result;
|
265
355
|
}
|
266
356
|
|
357
|
+
/* call-seq:
|
358
|
+
* query(sql, *parameters, &block)
|
359
|
+
* query_hash(sql, *parameters, &block)
|
360
|
+
*
|
361
|
+
* Runs a query returning rows as hashes (with symbol keys). If a block is
|
362
|
+
* given, it will be called for each row. Otherwise, an array containing all
|
363
|
+
* rows is returned.
|
364
|
+
*
|
365
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
366
|
+
* a list of values or as a hash mapping parameter names to values. When
|
367
|
+
* parameters are given as a least, the query should specify parameters using
|
368
|
+
* `?`:
|
369
|
+
*
|
370
|
+
* db.query('select * from foo where x = ?', 42)
|
371
|
+
*
|
372
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
373
|
+
* specified using a hash, where keys are either strings are symbols. String
|
374
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
375
|
+
*
|
376
|
+
* db.query('select * from foo where x = :bar', bar: 42)
|
377
|
+
* db.query('select * from foo where x = :bar', 'bar' => 42)
|
378
|
+
* db.query('select * from foo where x = :bar', ':bar' => 42)
|
379
|
+
*/
|
267
380
|
VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
|
268
381
|
query_ctx ctx = { self, argc, argv, 0 };
|
269
382
|
return rb_ensure(safe_query_hash, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
|
@@ -292,12 +405,32 @@ VALUE safe_query_ary(VALUE arg) {
|
|
292
405
|
row = row_to_ary(ctx->stmt, column_count);
|
293
406
|
if (yield_to_block) rb_yield(row); else rb_ary_push(result, row);
|
294
407
|
}
|
295
|
-
|
408
|
+
|
296
409
|
RB_GC_GUARD(row);
|
297
410
|
RB_GC_GUARD(result);
|
298
411
|
return result;
|
299
412
|
}
|
300
413
|
|
414
|
+
/* call-seq: query_ary(sql, *parameters, &block)
|
415
|
+
*
|
416
|
+
* Runs a query returning rows as arrays. If a block is given, it will be called
|
417
|
+
* for each row. Otherwise, an array containing all rows is returned.
|
418
|
+
*
|
419
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
420
|
+
* a list of values or as a hash mapping parameter names to values. When
|
421
|
+
* parameters are given as a least, the query should specify parameters using
|
422
|
+
* `?`:
|
423
|
+
*
|
424
|
+
* db.query_ary('select * from foo where x = ?', 42)
|
425
|
+
*
|
426
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
427
|
+
* specified using a hash, where keys are either strings are symbols. String
|
428
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
429
|
+
*
|
430
|
+
* db.query_ary('select * from foo where x = :bar', bar: 42)
|
431
|
+
* db.query_ary('select * from foo where x = :bar', 'bar' => 42)
|
432
|
+
* db.query_ary('select * from foo where x = :bar', ':bar' => 42)
|
433
|
+
*/
|
301
434
|
VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
|
302
435
|
query_ctx ctx = { self, argc, argv, 0 };
|
303
436
|
return rb_ensure(safe_query_ary, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
|
@@ -327,6 +460,25 @@ VALUE safe_query_single_row(VALUE arg) {
|
|
327
460
|
return row;
|
328
461
|
}
|
329
462
|
|
463
|
+
/* call-seq: query_single_row(sql, *parameters)
|
464
|
+
*
|
465
|
+
* Runs a query returning a single row as a hash.
|
466
|
+
*
|
467
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
468
|
+
* a list of values or as a hash mapping parameter names to values. When
|
469
|
+
* parameters are given as a least, the query should specify parameters using
|
470
|
+
* `?`:
|
471
|
+
*
|
472
|
+
* db.query_single_row('select * from foo where x = ?', 42)
|
473
|
+
*
|
474
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
475
|
+
* specified using a hash, where keys are either strings are symbols. String
|
476
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
477
|
+
*
|
478
|
+
* db.query_single_row('select * from foo where x = :bar', bar: 42)
|
479
|
+
* db.query_single_row('select * from foo where x = :bar', 'bar' => 42)
|
480
|
+
* db.query_single_row('select * from foo where x = :bar', ':bar' => 42)
|
481
|
+
*/
|
330
482
|
VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
|
331
483
|
query_ctx ctx = { self, argc, argv, 0 };
|
332
484
|
return rb_ensure(safe_query_single_row, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
|
@@ -364,6 +516,26 @@ VALUE safe_query_single_column(VALUE arg) {
|
|
364
516
|
return result;
|
365
517
|
}
|
366
518
|
|
519
|
+
/* call-seq: query_single_column(sql, *parameters, &block)
|
520
|
+
*
|
521
|
+
* Runs a query returning single column values. If a block is given, it will be called
|
522
|
+
* for each value. Otherwise, an array containing all values is returned.
|
523
|
+
*
|
524
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
525
|
+
* a list of values or as a hash mapping parameter names to values. When
|
526
|
+
* parameters are given as a least, the query should specify parameters using
|
527
|
+
* `?`:
|
528
|
+
*
|
529
|
+
* db.query_single_column('select x from foo where x = ?', 42)
|
530
|
+
*
|
531
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
532
|
+
* specified using a hash, where keys are either strings are symbols. String
|
533
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
534
|
+
*
|
535
|
+
* db.query_single_column('select x from foo where x = :bar', bar: 42)
|
536
|
+
* db.query_single_column('select x from foo where x = :bar', 'bar' => 42)
|
537
|
+
* db.query_single_column('select x from foo where x = :bar', ':bar' => 42)
|
538
|
+
*/
|
367
539
|
VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
|
368
540
|
query_ctx ctx = { self, argc, argv, 0 };
|
369
541
|
return rb_ensure(safe_query_single_column, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
|
@@ -392,11 +564,34 @@ VALUE safe_query_single_value(VALUE arg) {
|
|
392
564
|
return value;
|
393
565
|
}
|
394
566
|
|
567
|
+
/* call-seq: query_single_value(sql, *parameters)
|
568
|
+
*
|
569
|
+
* Runs a query returning a single value from the first row.
|
570
|
+
*
|
571
|
+
* Query parameters to be bound to placeholders in the query can be specified as
|
572
|
+
* a list of values or as a hash mapping parameter names to values. When
|
573
|
+
* parameters are given as a least, the query should specify parameters using
|
574
|
+
* `?`:
|
575
|
+
*
|
576
|
+
* db.query_single_value('select x from foo where x = ?', 42)
|
577
|
+
*
|
578
|
+
* Named placeholders are specified using `:`. The placeholder values are
|
579
|
+
* specified using a hash, where keys are either strings are symbols. String
|
580
|
+
* keys can include or omit the `:` prefix. The following are equivalent:
|
581
|
+
*
|
582
|
+
* db.query_single_value('select x from foo where x = :bar', bar: 42)
|
583
|
+
* db.query_single_value('select x from foo where x = :bar', 'bar' => 42)
|
584
|
+
* db.query_single_value('select x from foo where x = :bar', ':bar' => 42)
|
585
|
+
*/
|
395
586
|
VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
396
587
|
query_ctx ctx = { self, argc, argv, 0 };
|
397
588
|
return rb_ensure(safe_query_single_value, (VALUE)&ctx, cleanup_stmt, (VALUE)&ctx);
|
398
589
|
}
|
399
590
|
|
591
|
+
/* call-seq: last_insert_rowid
|
592
|
+
*
|
593
|
+
* Returns the rowid of the last inserted row.
|
594
|
+
*/
|
400
595
|
VALUE Database_last_insert_rowid(VALUE self) {
|
401
596
|
Database_t *db;
|
402
597
|
GetOpenDatabase(self, db);
|
@@ -404,6 +599,10 @@ VALUE Database_last_insert_rowid(VALUE self) {
|
|
404
599
|
return INT2NUM(sqlite3_last_insert_rowid(db->sqlite3_db));
|
405
600
|
}
|
406
601
|
|
602
|
+
/* call-seq: changes
|
603
|
+
*
|
604
|
+
* Returns the number of changes made to the database by the last operation.
|
605
|
+
*/
|
407
606
|
VALUE Database_changes(VALUE self) {
|
408
607
|
Database_t *db;
|
409
608
|
GetOpenDatabase(self, db);
|
@@ -411,6 +610,10 @@ VALUE Database_changes(VALUE self) {
|
|
411
610
|
return INT2NUM(sqlite3_changes(db->sqlite3_db));
|
412
611
|
}
|
413
612
|
|
613
|
+
/* call-seq: filename
|
614
|
+
*
|
615
|
+
* Returns the database filename.
|
616
|
+
*/
|
414
617
|
VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
|
415
618
|
const char *db_name;
|
416
619
|
const char *filename;
|
@@ -423,6 +626,10 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
|
|
423
626
|
return filename ? rb_str_new_cstr(filename) : Qnil;
|
424
627
|
}
|
425
628
|
|
629
|
+
/* call-seq: transaction_active?
|
630
|
+
*
|
631
|
+
* Returns true if a transaction is currently in progress.
|
632
|
+
*/
|
426
633
|
VALUE Database_transaction_active_p(VALUE self) {
|
427
634
|
Database_t *db;
|
428
635
|
GetOpenDatabase(self, db);
|
@@ -430,6 +637,10 @@ VALUE Database_transaction_active_p(VALUE self) {
|
|
430
637
|
return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
|
431
638
|
}
|
432
639
|
|
640
|
+
/* call-seq: load_extension(path)
|
641
|
+
*
|
642
|
+
* Loads an extension with the given path.
|
643
|
+
*/
|
433
644
|
VALUE Database_load_extension(VALUE self, VALUE path) {
|
434
645
|
Database_t *db;
|
435
646
|
GetOpenDatabase(self, db);
|
@@ -453,14 +664,14 @@ void Init_Extralite() {
|
|
453
664
|
rb_define_method(cDatabase, "initialize", Database_initialize, 1);
|
454
665
|
rb_define_method(cDatabase, "close", Database_close, 0);
|
455
666
|
rb_define_method(cDatabase, "closed?", Database_closed_p, 0);
|
456
|
-
|
667
|
+
|
457
668
|
rb_define_method(cDatabase, "query", Database_query_hash, -1);
|
458
669
|
rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
|
459
670
|
rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
|
460
671
|
rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
|
461
672
|
rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
|
462
673
|
rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
|
463
|
-
|
674
|
+
|
464
675
|
rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
|
465
676
|
rb_define_method(cDatabase, "changes", Database_changes, 0);
|
466
677
|
rb_define_method(cDatabase, "filename", Database_filename, -1);
|
@@ -474,5 +685,7 @@ void Init_Extralite() {
|
|
474
685
|
rb_gc_register_mark_object(cSQLError);
|
475
686
|
rb_gc_register_mark_object(cBusyError);
|
476
687
|
|
477
|
-
|
688
|
+
ID_KEYS = rb_intern("keys");
|
689
|
+
ID_STRIP = rb_intern("strip");
|
690
|
+
ID_TO_S = rb_intern("to_s");
|
478
691
|
}
|
data/extralite.gemspec
CHANGED
@@ -11,7 +11,6 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = 'https://github.com/digital-fabric/extralite'
|
12
12
|
s.metadata = {
|
13
13
|
"source_code_uri" => "https://github.com/digital-fabric/extralite",
|
14
|
-
"documentation_uri" => "https://github.com/digital-fabric/extralite",
|
15
14
|
"homepage_uri" => "https://github.com/digital-fabric/extralite",
|
16
15
|
"changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
|
17
16
|
}
|
@@ -21,9 +20,10 @@ Gem::Specification.new do |s|
|
|
21
20
|
s.require_paths = ["lib"]
|
22
21
|
s.required_ruby_version = '>= 2.6'
|
23
22
|
|
24
|
-
s.add_development_dependency 'rake-compiler', '1.1.
|
25
|
-
s.add_development_dependency 'minitest', '5.
|
23
|
+
s.add_development_dependency 'rake-compiler', '1.1.6'
|
24
|
+
s.add_development_dependency 'minitest', '5.15.0'
|
26
25
|
s.add_development_dependency 'simplecov', '0.17.1'
|
27
|
-
s.add_development_dependency '
|
28
|
-
|
26
|
+
s.add_development_dependency 'yard', '0.9.27'
|
27
|
+
|
28
|
+
s.add_development_dependency 'sequel', '5.51.0'
|
29
29
|
end
|
data/lib/extralite/version.rb
CHANGED
data/lib/extralite.rb
CHANGED
@@ -1 +1,21 @@
|
|
1
1
|
require_relative './extralite_ext'
|
2
|
+
|
3
|
+
# Extralite is a Ruby gem for working with SQLite databases
|
4
|
+
module Extralite
|
5
|
+
# A base class for Extralite exceptions
|
6
|
+
class Error < RuntimeError
|
7
|
+
end
|
8
|
+
|
9
|
+
# An exception representing an SQL error emitted by SQLite
|
10
|
+
class SQLError < Error
|
11
|
+
end
|
12
|
+
|
13
|
+
# An exception raised when an SQLite database is busy (locked by another
|
14
|
+
# thread or process)
|
15
|
+
class BusyError < Error
|
16
|
+
end
|
17
|
+
|
18
|
+
# An SQLite database
|
19
|
+
class Database
|
20
|
+
end
|
21
|
+
end
|