extralite 0.2 → 0.6
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/CHANGELOG.md +17 -1
- data/Gemfile.lock +1 -1
- data/README.md +6 -2
- data/ext/extralite/extralite.c +138 -55
- data/extralite.gemspec +2 -2
- data/lib/extralite/version.rb +1 -1
- data/test/test_database.rb +42 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 89b99ba7c6d26fc887574bf943f8e07f4c27f0c058a99723be73d7b64a90b3d5
|
4
|
+
data.tar.gz: 41c9bc62b91d78d0507d58b6a3e150608aae813b7b929410f23b0389a8b8c98f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6c29b92468cdf3a2fe9f65088c579a901ff981b11c68d8dc32c99508c4ab7fae5a8d9a348e2310dcf18b0980edac9f3503889de76e097c6d27c6c3fb20480245
|
7
|
+
data.tar.gz: 49c703000e9285cff90dadd0d64f40690d96a6f6c59305021dca0561d41aff6fedcc64a4918ce16337acbb7537fd91c73f2b1d65953cdff8be591773844c3465
|
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,20 @@
|
|
1
|
-
## 0.
|
1
|
+
## 0.6 2021-05-25
|
2
|
+
|
3
|
+
- Add more specific errors: `SQLError`, `BusyError`
|
4
|
+
|
5
|
+
## 0.5 2021-05-25
|
6
|
+
|
7
|
+
- Implement `Database#query_single_row`
|
8
|
+
|
9
|
+
## 0.4 2021-05-24
|
10
|
+
|
11
|
+
- Add support for loading extensions
|
12
|
+
|
13
|
+
## 0.3 2021-05-24
|
14
|
+
|
15
|
+
- Add support for running multiple statements
|
16
|
+
|
17
|
+
## 0.2 2021-05-23
|
2
18
|
|
3
19
|
- Implement `Database#transaction_active?`
|
4
20
|
- Add tests
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -5,12 +5,13 @@ class with a minimal set of methods to interact with an SQLite3 database.
|
|
5
5
|
|
6
6
|
### Features
|
7
7
|
|
8
|
-
- A variety of
|
9
|
-
column, single value.
|
8
|
+
- A variety of methods for different data access patterns: row as hash, row as array, single
|
9
|
+
single row, single column, single value.
|
10
10
|
- Iterate over records with a block, or collect records into an array.
|
11
11
|
- Parameter binding.
|
12
12
|
- Get last insert rowid.
|
13
13
|
- Get number of rows changed by last query.
|
14
|
+
- Load extensions.
|
14
15
|
|
15
16
|
### Usage
|
16
17
|
|
@@ -34,6 +35,9 @@ db.query_ary('select 1, 2, 3') #=> [[1, 2, 3]]
|
|
34
35
|
db.query_ary('select 1, 2, 3') { |r| p r }
|
35
36
|
# [1, 2, 3]
|
36
37
|
|
38
|
+
# get a single row as a hash
|
39
|
+
db.query_single_row("select 1 as foo") #=> { :foo => 1 }
|
40
|
+
|
37
41
|
# get single column query results as array of values
|
38
42
|
db.query_single_column('select 42') #=> [42]
|
39
43
|
# or iterate over results
|
data/ext/extralite/extralite.c
CHANGED
@@ -3,6 +3,9 @@
|
|
3
3
|
#include "../sqlite3/sqlite3.h"
|
4
4
|
|
5
5
|
VALUE cError;
|
6
|
+
VALUE cSQLError;
|
7
|
+
VALUE cBusyError;
|
8
|
+
ID ID_STRIP;
|
6
9
|
|
7
10
|
typedef struct Database_t {
|
8
11
|
sqlite3 *sqlite3_db;
|
@@ -44,10 +47,14 @@ VALUE Database_initialize(VALUE self, VALUE path) {
|
|
44
47
|
|
45
48
|
rc = sqlite3_open(StringValueCStr(path), &db->sqlite3_db);
|
46
49
|
if (rc) {
|
47
|
-
fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db->sqlite3_db));
|
48
50
|
sqlite3_close(db->sqlite3_db);
|
49
|
-
|
50
|
-
|
51
|
+
rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
52
|
+
}
|
53
|
+
|
54
|
+
rc = sqlite3_enable_load_extension(db->sqlite3_db, 1);
|
55
|
+
if (rc) {
|
56
|
+
sqlite3_close(db->sqlite3_db);
|
57
|
+
rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
51
58
|
}
|
52
59
|
|
53
60
|
return Qnil;
|
@@ -123,6 +130,41 @@ static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, VALUE colu
|
|
123
130
|
return row;
|
124
131
|
}
|
125
132
|
|
133
|
+
static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
|
134
|
+
VALUE row = rb_ary_new2(column_count);
|
135
|
+
for (int i = 0; i < column_count; i++) {
|
136
|
+
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
137
|
+
rb_ary_push(row, value);
|
138
|
+
}
|
139
|
+
return row;
|
140
|
+
}
|
141
|
+
|
142
|
+
inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
|
143
|
+
const char *rest = 0;
|
144
|
+
const char *ptr = RSTRING_PTR(sql);
|
145
|
+
const char *end = ptr + RSTRING_LEN(sql);
|
146
|
+
while (1) {
|
147
|
+
int rc = sqlite3_prepare(db, ptr, end - ptr, stmt, &rest);
|
148
|
+
if (rc) {
|
149
|
+
sqlite3_finalize(*stmt);
|
150
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
|
151
|
+
}
|
152
|
+
|
153
|
+
if (rest == end) return;
|
154
|
+
|
155
|
+
// perform current query, but discard its results
|
156
|
+
rc = sqlite3_step(*stmt);
|
157
|
+
sqlite3_finalize(*stmt);
|
158
|
+
switch (rc) {
|
159
|
+
case SQLITE_BUSY:
|
160
|
+
rb_raise(cBusyError, "Database is busy");
|
161
|
+
case SQLITE_ERROR:
|
162
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
|
163
|
+
}
|
164
|
+
ptr = rest;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
126
168
|
VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
|
127
169
|
int rc;
|
128
170
|
sqlite3_stmt* stmt;
|
@@ -135,16 +177,12 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
|
|
135
177
|
VALUE sql;
|
136
178
|
|
137
179
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
138
|
-
sql = argv[0];
|
139
|
-
|
180
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
181
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
140
182
|
|
141
|
-
|
142
|
-
if (rc) {
|
143
|
-
sqlite3_finalize(stmt);
|
144
|
-
rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
145
|
-
return Qnil;
|
146
|
-
}
|
183
|
+
GetDatabase(self, db);
|
147
184
|
|
185
|
+
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
148
186
|
bind_all_parameters(stmt, argc, argv);
|
149
187
|
column_count = sqlite3_column_count(stmt);
|
150
188
|
column_names = get_column_names(stmt, column_count);
|
@@ -163,10 +201,10 @@ step:
|
|
163
201
|
break;
|
164
202
|
case SQLITE_BUSY:
|
165
203
|
sqlite3_finalize(stmt);
|
166
|
-
rb_raise(
|
204
|
+
rb_raise(cBusyError, "Database is busy");
|
167
205
|
case SQLITE_ERROR:
|
168
206
|
sqlite3_finalize(stmt);
|
169
|
-
rb_raise(
|
207
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
170
208
|
default:
|
171
209
|
sqlite3_finalize(stmt);
|
172
210
|
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
@@ -179,15 +217,6 @@ step:
|
|
179
217
|
return result;
|
180
218
|
}
|
181
219
|
|
182
|
-
static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
|
183
|
-
VALUE row = rb_ary_new2(column_count);
|
184
|
-
for (int i = 0; i < column_count; i++) {
|
185
|
-
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
186
|
-
rb_ary_push(row, value);
|
187
|
-
}
|
188
|
-
return row;
|
189
|
-
}
|
190
|
-
|
191
220
|
VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
|
192
221
|
int rc;
|
193
222
|
sqlite3_stmt* stmt;
|
@@ -199,17 +228,11 @@ VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
|
|
199
228
|
VALUE sql;
|
200
229
|
|
201
230
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
202
|
-
sql = argv[0];
|
231
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
232
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
203
233
|
GetDatabase(self, db);
|
204
234
|
|
205
|
-
|
206
|
-
if (rc) {
|
207
|
-
fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db->sqlite3_db));
|
208
|
-
sqlite3_finalize(stmt);
|
209
|
-
// TODO: raise error
|
210
|
-
return Qfalse;
|
211
|
-
}
|
212
|
-
|
235
|
+
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
213
236
|
bind_all_parameters(stmt, argc, argv);
|
214
237
|
column_count = sqlite3_column_count(stmt);
|
215
238
|
|
@@ -225,10 +248,13 @@ step:
|
|
225
248
|
case SQLITE_DONE:
|
226
249
|
break;
|
227
250
|
case SQLITE_BUSY:
|
228
|
-
|
251
|
+
sqlite3_finalize(stmt);
|
252
|
+
rb_raise(cBusyError, "Database is busy");
|
229
253
|
case SQLITE_ERROR:
|
230
|
-
|
254
|
+
sqlite3_finalize(stmt);
|
255
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
231
256
|
default:
|
257
|
+
sqlite3_finalize(stmt);
|
232
258
|
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
233
259
|
}
|
234
260
|
sqlite3_finalize(stmt);
|
@@ -237,6 +263,47 @@ step:
|
|
237
263
|
return result;
|
238
264
|
}
|
239
265
|
|
266
|
+
VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
|
267
|
+
int rc;
|
268
|
+
sqlite3_stmt* stmt;
|
269
|
+
int column_count;
|
270
|
+
Database_t *db;
|
271
|
+
VALUE sql;
|
272
|
+
VALUE row = Qnil;
|
273
|
+
VALUE column_names;
|
274
|
+
|
275
|
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
276
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
277
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
278
|
+
|
279
|
+
GetDatabase(self, db);
|
280
|
+
|
281
|
+
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
282
|
+
bind_all_parameters(stmt, argc, argv);
|
283
|
+
column_count = sqlite3_column_count(stmt);
|
284
|
+
column_names = get_column_names(stmt, column_count);
|
285
|
+
|
286
|
+
rc = sqlite3_step(stmt);
|
287
|
+
switch (rc) {
|
288
|
+
case SQLITE_ROW:
|
289
|
+
row = row_to_hash(stmt, column_count, column_names);
|
290
|
+
break;
|
291
|
+
case SQLITE_DONE:
|
292
|
+
break;
|
293
|
+
case SQLITE_BUSY:
|
294
|
+
rb_raise(cBusyError, "Database is busy");
|
295
|
+
case SQLITE_ERROR:
|
296
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
297
|
+
default:
|
298
|
+
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
299
|
+
}
|
300
|
+
|
301
|
+
sqlite3_finalize(stmt);
|
302
|
+
RB_GC_GUARD(row);
|
303
|
+
RB_GC_GUARD(column_names);
|
304
|
+
return row;
|
305
|
+
}
|
306
|
+
|
240
307
|
VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
|
241
308
|
int rc;
|
242
309
|
sqlite3_stmt* stmt;
|
@@ -248,17 +315,12 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
|
|
248
315
|
VALUE value;
|
249
316
|
|
250
317
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
251
|
-
sql = argv[0];
|
252
|
-
|
318
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
319
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
253
320
|
|
254
|
-
|
255
|
-
if (rc) {
|
256
|
-
fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db->sqlite3_db));
|
257
|
-
sqlite3_finalize(stmt);
|
258
|
-
// TODO: raise error
|
259
|
-
return Qfalse;
|
260
|
-
}
|
321
|
+
GetDatabase(self, db);
|
261
322
|
|
323
|
+
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
262
324
|
bind_all_parameters(stmt, argc, argv);
|
263
325
|
column_count = sqlite3_column_count(stmt);
|
264
326
|
if (column_count != 1)
|
@@ -276,10 +338,13 @@ step:
|
|
276
338
|
case SQLITE_DONE:
|
277
339
|
break;
|
278
340
|
case SQLITE_BUSY:
|
279
|
-
|
341
|
+
sqlite3_finalize(stmt);
|
342
|
+
rb_raise(cBusyError, "Database is busy");
|
280
343
|
case SQLITE_ERROR:
|
281
|
-
|
344
|
+
sqlite3_finalize(stmt);
|
345
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
282
346
|
default:
|
347
|
+
sqlite3_finalize(stmt);
|
283
348
|
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
284
349
|
}
|
285
350
|
|
@@ -298,17 +363,12 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
|
298
363
|
VALUE value = Qnil;
|
299
364
|
|
300
365
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
301
|
-
sql = argv[0];
|
302
|
-
|
366
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
367
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
303
368
|
|
304
|
-
|
305
|
-
if (rc) {
|
306
|
-
fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db->sqlite3_db));
|
307
|
-
sqlite3_finalize(stmt);
|
308
|
-
// TODO: raise error
|
309
|
-
return Qfalse;
|
310
|
-
}
|
369
|
+
GetDatabase(self, db);
|
311
370
|
|
371
|
+
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
312
372
|
bind_all_parameters(stmt, argc, argv);
|
313
373
|
column_count = sqlite3_column_count(stmt);
|
314
374
|
if (column_count != 1)
|
@@ -319,10 +379,12 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
|
319
379
|
case SQLITE_ROW:
|
320
380
|
value = get_column_value(stmt, 0, sqlite3_column_type(stmt, 0));
|
321
381
|
break;
|
382
|
+
case SQLITE_DONE:
|
383
|
+
break;
|
322
384
|
case SQLITE_BUSY:
|
323
|
-
rb_raise(
|
385
|
+
rb_raise(cBusyError, "Database is busy");
|
324
386
|
case SQLITE_ERROR:
|
325
|
-
rb_raise(
|
387
|
+
rb_raise(cSQLError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
326
388
|
default:
|
327
389
|
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
328
390
|
}
|
@@ -365,6 +427,21 @@ VALUE Database_transaction_active_p(VALUE self) {
|
|
365
427
|
return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
|
366
428
|
}
|
367
429
|
|
430
|
+
VALUE Database_load_extension(VALUE self, VALUE path) {
|
431
|
+
Database_t *db;
|
432
|
+
GetDatabase(self, db);
|
433
|
+
char *err_msg;
|
434
|
+
|
435
|
+
int rc = sqlite3_load_extension(db->sqlite3_db, RSTRING_PTR(path), 0, &err_msg);
|
436
|
+
if (rc != SQLITE_OK) {
|
437
|
+
VALUE error = rb_exc_new2(cError, err_msg);
|
438
|
+
sqlite3_free(err_msg);
|
439
|
+
rb_exc_raise(error);
|
440
|
+
}
|
441
|
+
|
442
|
+
return self;
|
443
|
+
}
|
444
|
+
|
368
445
|
void Init_Extralite() {
|
369
446
|
VALUE mExtralite = rb_define_module("Extralite");
|
370
447
|
VALUE cDatabase = rb_define_class_under(mExtralite, "Database", rb_cObject);
|
@@ -375,6 +452,7 @@ void Init_Extralite() {
|
|
375
452
|
rb_define_method(cDatabase, "query", Database_query_hash, -1);
|
376
453
|
rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
|
377
454
|
rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
|
455
|
+
rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
|
378
456
|
rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
|
379
457
|
rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
|
380
458
|
|
@@ -382,6 +460,11 @@ void Init_Extralite() {
|
|
382
460
|
rb_define_method(cDatabase, "changes", Database_changes, 0);
|
383
461
|
rb_define_method(cDatabase, "filename", Database_filename, -1);
|
384
462
|
rb_define_method(cDatabase, "transaction_active?", Database_transaction_active_p, 0);
|
463
|
+
rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
|
385
464
|
|
386
465
|
cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
|
466
|
+
cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
|
467
|
+
cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
|
468
|
+
|
469
|
+
ID_STRIP = rb_intern("strip");
|
387
470
|
}
|
data/extralite.gemspec
CHANGED
@@ -11,8 +11,8 @@ 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://digital-fabric
|
15
|
-
"homepage_uri" => "https://digital-fabric
|
14
|
+
"documentation_uri" => "https://github.com/digital-fabric/extralite",
|
15
|
+
"homepage_uri" => "https://github.com/digital-fabric/extralite",
|
16
16
|
"changelog_uri" => "https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md"
|
17
17
|
}
|
18
18
|
s.rdoc_options = ["--title", "extralite", "--main", "README.md"]
|
data/lib/extralite/version.rb
CHANGED
data/test/test_database.rb
CHANGED
@@ -19,26 +19,53 @@ class DatabaseTest < MiniTest::Test
|
|
19
19
|
def test_query
|
20
20
|
r = @db.query('select * from t')
|
21
21
|
assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
|
22
|
+
|
23
|
+
r = @db.query('select * from t where x = 2')
|
24
|
+
assert_equal [], r
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_invalid_query
|
28
|
+
assert_raises(Extralite::SQLError) { @db.query('blah') }
|
22
29
|
end
|
23
30
|
|
24
31
|
def test_query_hash
|
25
32
|
r = @db.query_hash('select * from t')
|
26
33
|
assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
|
34
|
+
|
35
|
+
r = @db.query_hash('select * from t where x = 2')
|
36
|
+
assert_equal [], r
|
27
37
|
end
|
28
38
|
|
29
39
|
def test_query_ary
|
30
40
|
r = @db.query_ary('select * from t')
|
31
41
|
assert_equal [[1, 2, 3], [4, 5, 6]], r
|
42
|
+
|
43
|
+
r = @db.query_ary('select * from t where x = 2')
|
44
|
+
assert_equal [], r
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_query_single_row
|
48
|
+
r = @db.query_single_row('select * from t order by x desc limit 1')
|
49
|
+
assert_equal({ x: 4, y: 5, z: 6 }, r)
|
50
|
+
|
51
|
+
r = @db.query_single_row('select * from t where x = 2')
|
52
|
+
assert_nil r
|
32
53
|
end
|
33
54
|
|
34
55
|
def test_query_single_column
|
35
56
|
r = @db.query_single_column('select y from t')
|
36
57
|
assert_equal [2, 5], r
|
37
|
-
|
58
|
+
|
59
|
+
r = @db.query_single_column('select y from t where x = 2')
|
60
|
+
assert_equal [], r
|
61
|
+
end
|
38
62
|
|
39
63
|
def test_query_single_value
|
40
64
|
r = @db.query_single_value('select z from t order by Z desc limit 1')
|
41
65
|
assert_equal 6, r
|
66
|
+
|
67
|
+
r = @db.query_single_value('select z from t where x = 2')
|
68
|
+
assert_nil r
|
42
69
|
end
|
43
70
|
|
44
71
|
def test_transaction_active?
|
@@ -48,4 +75,18 @@ class DatabaseTest < MiniTest::Test
|
|
48
75
|
@db.query('rollback')
|
49
76
|
assert_equal false, @db.transaction_active?
|
50
77
|
end
|
78
|
+
|
79
|
+
def test_multiple_statements
|
80
|
+
@db.query("insert into t values ('a', 'b', 'c'); insert into t values ('d', 'e', 'f');")
|
81
|
+
|
82
|
+
assert_equal [1, 4, 'a', 'd'], @db.query_single_column('select x from t order by x')
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_empty_sql
|
86
|
+
r = @db.query(' ')
|
87
|
+
assert_nil r
|
88
|
+
|
89
|
+
r = @db.query('select 1 as foo; ')
|
90
|
+
assert_equal [{ foo: 1 }], r
|
91
|
+
end
|
51
92
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: extralite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: '0.
|
4
|
+
version: '0.6'
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-05-
|
11
|
+
date: 2021-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -125,8 +125,8 @@ licenses:
|
|
125
125
|
- MIT
|
126
126
|
metadata:
|
127
127
|
source_code_uri: https://github.com/digital-fabric/extralite
|
128
|
-
documentation_uri: https://digital-fabric
|
129
|
-
homepage_uri: https://digital-fabric
|
128
|
+
documentation_uri: https://github.com/digital-fabric/extralite
|
129
|
+
homepage_uri: https://github.com/digital-fabric/extralite
|
130
130
|
changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
|
131
131
|
post_install_message:
|
132
132
|
rdoc_options:
|