extralite 0.4 → 0.5
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 +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +5 -2
- data/ext/extralite/extralite.c +66 -14
- data/lib/extralite/version.rb +1 -1
- data/test/test_database.rb +32 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8fa0672decf076e478bfd52359196baecbcf837e00cec91c7f9cf963b103af68
|
4
|
+
data.tar.gz: e54364225b96fc355a8198eab73c7a27848a672e04479a7eed06f724991ae238
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9606a7e0154d61adc29150161a44018638f7e05a3c17f4f8e8b992e166ad0cd46705cb4eab2e9e6f7cc7f4d9eece8406e468822ff8a84116ff6f58cc493a89dd
|
7
|
+
data.tar.gz: fa5e4e1425187986ec097990f84ae103428645f94caaa41471305b414c78f15fb9522311b4eb50d40bc91c715f9e20e1c2fac18c0fd02892b41e75994602691d
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -5,8 +5,8 @@ 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.
|
@@ -34,6 +34,9 @@ db.query_ary('select 1, 2, 3') #=> [[1, 2, 3]]
|
|
34
34
|
db.query_ary('select 1, 2, 3') { |r| p r }
|
35
35
|
# [1, 2, 3]
|
36
36
|
|
37
|
+
# get a single row as a hash
|
38
|
+
db.query_single_column("select 1 as foo") #=> { :foo => 1 }
|
39
|
+
|
37
40
|
# get single column query results as array of values
|
38
41
|
db.query_single_column('select 42') #=> [42]
|
39
42
|
# or iterate over results
|
data/ext/extralite/extralite.c
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
#include "../sqlite3/sqlite3.h"
|
4
4
|
|
5
5
|
VALUE cError;
|
6
|
+
ID ID_STRIP;
|
6
7
|
|
7
8
|
typedef struct Database_t {
|
8
9
|
sqlite3 *sqlite3_db;
|
@@ -127,6 +128,15 @@ static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, VALUE colu
|
|
127
128
|
return row;
|
128
129
|
}
|
129
130
|
|
131
|
+
static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
|
132
|
+
VALUE row = rb_ary_new2(column_count);
|
133
|
+
for (int i = 0; i < column_count; i++) {
|
134
|
+
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
135
|
+
rb_ary_push(row, value);
|
136
|
+
}
|
137
|
+
return row;
|
138
|
+
}
|
139
|
+
|
130
140
|
inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
|
131
141
|
const char *rest = 0;
|
132
142
|
const char *ptr = RSTRING_PTR(sql);
|
@@ -165,7 +175,9 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
|
|
165
175
|
VALUE sql;
|
166
176
|
|
167
177
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
168
|
-
sql = argv[0];
|
178
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
179
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
180
|
+
|
169
181
|
GetDatabase(self, db);
|
170
182
|
|
171
183
|
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
@@ -203,15 +215,6 @@ step:
|
|
203
215
|
return result;
|
204
216
|
}
|
205
217
|
|
206
|
-
static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
|
207
|
-
VALUE row = rb_ary_new2(column_count);
|
208
|
-
for (int i = 0; i < column_count; i++) {
|
209
|
-
VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
|
210
|
-
rb_ary_push(row, value);
|
211
|
-
}
|
212
|
-
return row;
|
213
|
-
}
|
214
|
-
|
215
218
|
VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
|
216
219
|
int rc;
|
217
220
|
sqlite3_stmt* stmt;
|
@@ -223,7 +226,8 @@ VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
|
|
223
226
|
VALUE sql;
|
224
227
|
|
225
228
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
226
|
-
sql = argv[0];
|
229
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
230
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
227
231
|
GetDatabase(self, db);
|
228
232
|
|
229
233
|
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
@@ -257,6 +261,47 @@ step:
|
|
257
261
|
return result;
|
258
262
|
}
|
259
263
|
|
264
|
+
VALUE Database_query_single_row(int argc, VALUE *argv, VALUE self) {
|
265
|
+
int rc;
|
266
|
+
sqlite3_stmt* stmt;
|
267
|
+
int column_count;
|
268
|
+
Database_t *db;
|
269
|
+
VALUE sql;
|
270
|
+
VALUE row = Qnil;
|
271
|
+
VALUE column_names;
|
272
|
+
|
273
|
+
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
274
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
275
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
276
|
+
|
277
|
+
GetDatabase(self, db);
|
278
|
+
|
279
|
+
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
280
|
+
bind_all_parameters(stmt, argc, argv);
|
281
|
+
column_count = sqlite3_column_count(stmt);
|
282
|
+
column_names = get_column_names(stmt, column_count);
|
283
|
+
|
284
|
+
rc = sqlite3_step(stmt);
|
285
|
+
switch (rc) {
|
286
|
+
case SQLITE_ROW:
|
287
|
+
row = row_to_hash(stmt, column_count, column_names);
|
288
|
+
break;
|
289
|
+
case SQLITE_DONE:
|
290
|
+
break;
|
291
|
+
case SQLITE_BUSY:
|
292
|
+
rb_raise(cError, "Database is busy");
|
293
|
+
case SQLITE_ERROR:
|
294
|
+
rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
|
295
|
+
default:
|
296
|
+
rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
|
297
|
+
}
|
298
|
+
|
299
|
+
sqlite3_finalize(stmt);
|
300
|
+
RB_GC_GUARD(row);
|
301
|
+
RB_GC_GUARD(column_names);
|
302
|
+
return row;
|
303
|
+
}
|
304
|
+
|
260
305
|
VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
|
261
306
|
int rc;
|
262
307
|
sqlite3_stmt* stmt;
|
@@ -268,7 +313,9 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
|
|
268
313
|
VALUE value;
|
269
314
|
|
270
315
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
271
|
-
sql = argv[0];
|
316
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
317
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
318
|
+
|
272
319
|
GetDatabase(self, db);
|
273
320
|
|
274
321
|
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
@@ -281,7 +328,6 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
|
|
281
328
|
if (!yield_to_block) result = rb_ary_new();
|
282
329
|
step:
|
283
330
|
rc = sqlite3_step(stmt);
|
284
|
-
printf("rc=%d\n", rc);
|
285
331
|
switch (rc) {
|
286
332
|
case SQLITE_ROW:
|
287
333
|
value = get_column_value(stmt, 0, sqlite3_column_type(stmt, 0));
|
@@ -315,7 +361,9 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
|
315
361
|
VALUE value = Qnil;
|
316
362
|
|
317
363
|
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
|
318
|
-
sql = argv[0];
|
364
|
+
sql = rb_funcall(argv[0], ID_STRIP, 0);
|
365
|
+
if (RSTRING_LEN(sql) == 0) return Qnil;
|
366
|
+
|
319
367
|
GetDatabase(self, db);
|
320
368
|
|
321
369
|
prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
|
@@ -329,6 +377,8 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
|
|
329
377
|
case SQLITE_ROW:
|
330
378
|
value = get_column_value(stmt, 0, sqlite3_column_type(stmt, 0));
|
331
379
|
break;
|
380
|
+
case SQLITE_DONE:
|
381
|
+
break;
|
332
382
|
case SQLITE_BUSY:
|
333
383
|
rb_raise(cError, "Database is busy");
|
334
384
|
case SQLITE_ERROR:
|
@@ -400,6 +450,7 @@ void Init_Extralite() {
|
|
400
450
|
rb_define_method(cDatabase, "query", Database_query_hash, -1);
|
401
451
|
rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
|
402
452
|
rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
|
453
|
+
rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
|
403
454
|
rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
|
404
455
|
rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
|
405
456
|
|
@@ -410,4 +461,5 @@ void Init_Extralite() {
|
|
410
461
|
rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
|
411
462
|
|
412
463
|
cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
|
464
|
+
ID_STRIP = rb_intern("strip");
|
413
465
|
}
|
data/lib/extralite/version.rb
CHANGED
data/test/test_database.rb
CHANGED
@@ -19,26 +19,49 @@ 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
|
22
25
|
end
|
23
26
|
|
24
27
|
def test_query_hash
|
25
28
|
r = @db.query_hash('select * from t')
|
26
29
|
assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
|
30
|
+
|
31
|
+
r = @db.query_hash('select * from t where x = 2')
|
32
|
+
assert_equal [], r
|
27
33
|
end
|
28
34
|
|
29
35
|
def test_query_ary
|
30
36
|
r = @db.query_ary('select * from t')
|
31
37
|
assert_equal [[1, 2, 3], [4, 5, 6]], r
|
38
|
+
|
39
|
+
r = @db.query_ary('select * from t where x = 2')
|
40
|
+
assert_equal [], r
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_query_single_row
|
44
|
+
r = @db.query_single_row('select * from t order by x desc limit 1')
|
45
|
+
assert_equal({ x: 4, y: 5, z: 6 }, r)
|
46
|
+
|
47
|
+
r = @db.query_single_row('select * from t where x = 2')
|
48
|
+
assert_nil r
|
32
49
|
end
|
33
50
|
|
34
51
|
def test_query_single_column
|
35
52
|
r = @db.query_single_column('select y from t')
|
36
53
|
assert_equal [2, 5], r
|
37
|
-
|
54
|
+
|
55
|
+
r = @db.query_single_column('select y from t where x = 2')
|
56
|
+
assert_equal [], r
|
57
|
+
end
|
38
58
|
|
39
59
|
def test_query_single_value
|
40
60
|
r = @db.query_single_value('select z from t order by Z desc limit 1')
|
41
61
|
assert_equal 6, r
|
62
|
+
|
63
|
+
r = @db.query_single_value('select z from t where x = 2')
|
64
|
+
assert_nil r
|
42
65
|
end
|
43
66
|
|
44
67
|
def test_transaction_active?
|
@@ -54,4 +77,12 @@ class DatabaseTest < MiniTest::Test
|
|
54
77
|
|
55
78
|
assert_equal [1, 4, 'a', 'd'], @db.query_single_column('select x from t order by x')
|
56
79
|
end
|
80
|
+
|
81
|
+
def test_empty_sql
|
82
|
+
r = @db.query(' ')
|
83
|
+
assert_nil r
|
84
|
+
|
85
|
+
r = @db.query('select 1 as foo; ')
|
86
|
+
assert_equal [{ foo: 1 }], r
|
87
|
+
end
|
57
88
|
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.5'
|
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
|