extralite 1.4 → 1.8.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|