extralite 0.1 → 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6467de8ba44e1e77c57965e0360a18f9e2cf97084f0c507d0b1946e2cb0bb153
4
- data.tar.gz: a12610ea4fab0207d5360f5410428ab7d8ce004c98ecd05fcb13785bf173c196
3
+ metadata.gz: 8fa0672decf076e478bfd52359196baecbcf837e00cec91c7f9cf963b103af68
4
+ data.tar.gz: e54364225b96fc355a8198eab73c7a27848a672e04479a7eed06f724991ae238
5
5
  SHA512:
6
- metadata.gz: 5c17e8b73c0e94718a80bdcce58c98072c640b952959b441c7053f367984650688ee25ce5d7e0c6c4706d9d13d688f6e006c336e78c0c803d35af3a9cab15885
7
- data.tar.gz: 194b2b8e9d469927e08bb6bc9b9e88238fb2b289bace6501c736817cfdee29e4c13d20d420a1a344c107ce039786b703826a11091a8f2eb3cc366dde6f922d46
6
+ metadata.gz: 9606a7e0154d61adc29150161a44018638f7e05a3c17f4f8e8b992e166ad0cd46705cb4eab2e9e6f7cc7f4d9eece8406e468822ff8a84116ff6f58cc493a89dd
7
+ data.tar.gz: fa5e4e1425187986ec097990f84ae103428645f94caaa41471305b414c78f15fb9522311b4eb50d40bc91c715f9e20e1c2fac18c0fd02892b41e75994602691d
@@ -0,0 +1,31 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ build:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu-latest]
11
+ ruby: [2.6, 2.7, 3.0]
12
+
13
+ name: >-
14
+ ${{matrix.os}}, ${{matrix.ruby}}
15
+
16
+ runs-on: ${{matrix.os}}
17
+ steps:
18
+ - uses: actions/checkout@v1
19
+ - uses: actions/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{matrix.ruby}}
22
+ - name: Install dependencies
23
+ run: |
24
+ gem install bundler
25
+ bundle install
26
+ - name: Show Linux kernel version
27
+ run: uname -r
28
+ - name: Compile C-extension
29
+ run: bundle exec rake compile
30
+ - name: Run tests
31
+ run: bundle exec rake test
data/CHANGELOG.md CHANGED
@@ -0,0 +1,21 @@
1
+ ## 0.5 2021-05-25
2
+
3
+ - Implement `Database#query_single_row`
4
+
5
+ ## 0.4 2021-05-24
6
+
7
+ - Add support for loading extensions
8
+
9
+ ## 0.3 2021-05-24
10
+
11
+ - Add support for running multiple statements
12
+
13
+ ## 0.2 2021-05-23
14
+
15
+ - Implement `Database#transaction_active?`
16
+ - Add tests
17
+
18
+ ## 0.1 2021-05-21
19
+
20
+ - First release
21
+
data/Gemfile CHANGED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,66 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ extralite (0.5)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ ansi (1.5.0)
10
+ ast (2.4.2)
11
+ builder (3.2.4)
12
+ coderay (1.1.3)
13
+ docile (1.4.0)
14
+ json (2.5.1)
15
+ method_source (1.0.0)
16
+ minitest (5.14.4)
17
+ minitest-reporters (1.4.2)
18
+ ansi
19
+ builder
20
+ minitest (>= 5.0)
21
+ ruby-progressbar
22
+ parallel (1.20.1)
23
+ parser (3.0.1.1)
24
+ ast (~> 2.4.1)
25
+ pry (0.13.1)
26
+ coderay (~> 1.1)
27
+ method_source (~> 1.0)
28
+ rainbow (3.0.0)
29
+ rake (13.0.3)
30
+ rake-compiler (1.1.1)
31
+ rake
32
+ regexp_parser (2.1.1)
33
+ rexml (3.2.5)
34
+ rubocop (0.85.1)
35
+ parallel (~> 1.10)
36
+ parser (>= 2.7.0.1)
37
+ rainbow (>= 2.2.2, < 4.0)
38
+ regexp_parser (>= 1.7)
39
+ rexml
40
+ rubocop-ast (>= 0.0.3)
41
+ ruby-progressbar (~> 1.7)
42
+ unicode-display_width (>= 1.4.0, < 2.0)
43
+ rubocop-ast (1.5.0)
44
+ parser (>= 3.0.1.1)
45
+ ruby-progressbar (1.11.0)
46
+ simplecov (0.17.1)
47
+ docile (~> 1.1)
48
+ json (>= 1.8, < 3)
49
+ simplecov-html (~> 0.10.0)
50
+ simplecov-html (0.10.2)
51
+ unicode-display_width (1.7.0)
52
+
53
+ PLATFORMS
54
+ ruby
55
+
56
+ DEPENDENCIES
57
+ extralite!
58
+ minitest (= 5.14.4)
59
+ minitest-reporters (= 1.4.2)
60
+ pry (= 0.13.1)
61
+ rake-compiler (= 1.1.1)
62
+ rubocop (= 0.85.1)
63
+ simplecov (= 0.17.1)
64
+
65
+ BUNDLED WITH
66
+ 2.1.4
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2021 Digital Fabric
3
+ Copyright (c) 2021 Sharon Rosner
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
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 ways to get back query results: row as hash, row as array, single
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.
@@ -21,9 +21,11 @@ require 'extralite'
21
21
  db = Extralite::Database.new('mydb')
22
22
 
23
23
  # get query results as array of hashes
24
+ db.query('select 1 as foo') #=> [{ :foo => 1 }]
25
+ # or:
24
26
  db.query_hash('select 1 as foo') #=> [{ :foo => 1 }]
25
27
  # or iterate over results
26
- db.query_hash('select 1 as foo') { |r| p r }
28
+ db.query('select 1 as foo') { |r| p r }
27
29
  # { :foo => 1 }
28
30
 
29
31
  # get query results as array of arrays
@@ -32,6 +34,9 @@ db.query_ary('select 1, 2, 3') #=> [[1, 2, 3]]
32
34
  db.query_ary('select 1, 2, 3') { |r| p r }
33
35
  # [1, 2, 3]
34
36
 
37
+ # get a single row as a hash
38
+ db.query_single_column("select 1 as foo") #=> { :foo => 1 }
39
+
35
40
  # get single column query results as array of values
36
41
  db.query_single_column('select 42') #=> [42]
37
42
  # or iterate over results
@@ -45,7 +50,11 @@ db.query_single_value("select 'foo'") #=> "foo"
45
50
  db.query_hash('select ? as foo, ? as bar', 1, 2) #=> [{ :foo => 1, :bar => 2 }]
46
51
 
47
52
  # get last insert rowid
48
- rowid = db.last_insert_id()
49
- ```
53
+ rowid = db.last_insert_id
50
54
 
55
+ # get rows changed in last query
56
+ rows_changed = db.changes
51
57
 
58
+ # get db filename
59
+ Extralite::Database.new('/tmp/my.db').filename #=> "/tmp/my.db"
60
+ ```
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ task :recompile => [:clean, :compile]
12
12
 
13
13
  task :default => [:compile, :test]
14
14
  task :test do
15
- exec 'ruby test/run.rb'
15
+ exec 'ruby test/test_database.rb'
16
16
  end
17
17
 
18
18
  CLEAN.include "**/*.o", "**/*.so", "**/*.so.*", "**/*.a", "**/*.bundle", "**/*.jar", "pkg", "tmp"
@@ -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;
@@ -44,10 +45,14 @@ VALUE Database_initialize(VALUE self, VALUE path) {
44
45
 
45
46
  rc = sqlite3_open(StringValueCStr(path), &db->sqlite3_db);
46
47
  if (rc) {
47
- fprintf(stderr, "Can't open database: %s\n", sqlite3_errmsg(db->sqlite3_db));
48
48
  sqlite3_close(db->sqlite3_db);
49
- // TODO: raise error
50
- return Qfalse;
49
+ rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
50
+ }
51
+
52
+ rc = sqlite3_enable_load_extension(db->sqlite3_db, 1);
53
+ if (rc) {
54
+ sqlite3_close(db->sqlite3_db);
55
+ rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
51
56
  }
52
57
 
53
58
  return Qnil;
@@ -123,6 +128,41 @@ static inline VALUE row_to_hash(sqlite3_stmt *stmt, int column_count, VALUE colu
123
128
  return row;
124
129
  }
125
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
+
140
+ inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
141
+ const char *rest = 0;
142
+ const char *ptr = RSTRING_PTR(sql);
143
+ const char *end = ptr + RSTRING_LEN(sql);
144
+ while (1) {
145
+ int rc = sqlite3_prepare(db, ptr, end - ptr, stmt, &rest);
146
+ if (rc) {
147
+ sqlite3_finalize(*stmt);
148
+ rb_raise(cError, "%s", sqlite3_errmsg(db));
149
+ }
150
+
151
+ if (rest == end) return;
152
+
153
+ // perform current query, but discard its results
154
+ rc = sqlite3_step(*stmt);
155
+ sqlite3_finalize(*stmt);
156
+ switch (rc) {
157
+ case SQLITE_BUSY:
158
+ rb_raise(cError, "Database is busy");
159
+ case SQLITE_ERROR:
160
+ rb_raise(cError, "%s", sqlite3_errmsg(db));
161
+ }
162
+ ptr = rest;
163
+ }
164
+ }
165
+
126
166
  VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
127
167
  int rc;
128
168
  sqlite3_stmt* stmt;
@@ -135,16 +175,12 @@ VALUE Database_query_hash(int argc, VALUE *argv, VALUE self) {
135
175
  VALUE sql;
136
176
 
137
177
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
138
- sql = argv[0];
139
- GetDatabase(self, db);
178
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
179
+ if (RSTRING_LEN(sql) == 0) return Qnil;
140
180
 
141
- rc = sqlite3_prepare(db->sqlite3_db, RSTRING_PTR(sql), RSTRING_LEN(sql), &stmt, 0);
142
- if (rc) {
143
- sqlite3_finalize(stmt);
144
- rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
145
- return Qnil;
146
- }
181
+ GetDatabase(self, db);
147
182
 
183
+ prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
148
184
  bind_all_parameters(stmt, argc, argv);
149
185
  column_count = sqlite3_column_count(stmt);
150
186
  column_names = get_column_names(stmt, column_count);
@@ -162,12 +198,16 @@ step:
162
198
  case SQLITE_DONE:
163
199
  break;
164
200
  case SQLITE_BUSY:
201
+ sqlite3_finalize(stmt);
165
202
  rb_raise(cError, "Database is busy");
166
203
  case SQLITE_ERROR:
204
+ sqlite3_finalize(stmt);
167
205
  rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
168
206
  default:
207
+ sqlite3_finalize(stmt);
169
208
  rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
170
209
  }
210
+ // TODO, use ensure to finalize statement
171
211
  sqlite3_finalize(stmt);
172
212
  RB_GC_GUARD(column_names);
173
213
  RB_GC_GUARD(row);
@@ -175,15 +215,6 @@ step:
175
215
  return result;
176
216
  }
177
217
 
178
- static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
179
- VALUE row = rb_ary_new2(column_count);
180
- for (int i = 0; i < column_count; i++) {
181
- VALUE value = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
182
- rb_ary_push(row, value);
183
- }
184
- return row;
185
- }
186
-
187
218
  VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
188
219
  int rc;
189
220
  sqlite3_stmt* stmt;
@@ -195,17 +226,11 @@ VALUE Database_query_ary(int argc, VALUE *argv, VALUE self) {
195
226
  VALUE sql;
196
227
 
197
228
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
198
- sql = argv[0];
229
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
230
+ if (RSTRING_LEN(sql) == 0) return Qnil;
199
231
  GetDatabase(self, db);
200
232
 
201
- rc = sqlite3_prepare(db->sqlite3_db, RSTRING_PTR(sql), RSTRING_LEN(sql), &stmt, 0);
202
- if (rc) {
203
- fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db->sqlite3_db));
204
- sqlite3_finalize(stmt);
205
- // TODO: raise error
206
- return Qfalse;
207
- }
208
-
233
+ prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
209
234
  bind_all_parameters(stmt, argc, argv);
210
235
  column_count = sqlite3_column_count(stmt);
211
236
 
@@ -221,10 +246,13 @@ step:
221
246
  case SQLITE_DONE:
222
247
  break;
223
248
  case SQLITE_BUSY:
249
+ sqlite3_finalize(stmt);
224
250
  rb_raise(cError, "Database is busy");
225
251
  case SQLITE_ERROR:
252
+ sqlite3_finalize(stmt);
226
253
  rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
227
254
  default:
255
+ sqlite3_finalize(stmt);
228
256
  rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
229
257
  }
230
258
  sqlite3_finalize(stmt);
@@ -233,6 +261,47 @@ step:
233
261
  return result;
234
262
  }
235
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
+
236
305
  VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
237
306
  int rc;
238
307
  sqlite3_stmt* stmt;
@@ -244,17 +313,12 @@ VALUE Database_query_single_column(int argc, VALUE *argv, VALUE self) {
244
313
  VALUE value;
245
314
 
246
315
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
247
- sql = argv[0];
248
- GetDatabase(self, db);
316
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
317
+ if (RSTRING_LEN(sql) == 0) return Qnil;
249
318
 
250
- rc = sqlite3_prepare(db->sqlite3_db, RSTRING_PTR(sql), RSTRING_LEN(sql), &stmt, 0);
251
- if (rc) {
252
- fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db->sqlite3_db));
253
- sqlite3_finalize(stmt);
254
- // TODO: raise error
255
- return Qfalse;
256
- }
319
+ GetDatabase(self, db);
257
320
 
321
+ prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
258
322
  bind_all_parameters(stmt, argc, argv);
259
323
  column_count = sqlite3_column_count(stmt);
260
324
  if (column_count != 1)
@@ -272,10 +336,13 @@ step:
272
336
  case SQLITE_DONE:
273
337
  break;
274
338
  case SQLITE_BUSY:
339
+ sqlite3_finalize(stmt);
275
340
  rb_raise(cError, "Database is busy");
276
341
  case SQLITE_ERROR:
342
+ sqlite3_finalize(stmt);
277
343
  rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
278
344
  default:
345
+ sqlite3_finalize(stmt);
279
346
  rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
280
347
  }
281
348
 
@@ -294,17 +361,12 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
294
361
  VALUE value = Qnil;
295
362
 
296
363
  rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
297
- sql = argv[0];
298
- GetDatabase(self, db);
364
+ sql = rb_funcall(argv[0], ID_STRIP, 0);
365
+ if (RSTRING_LEN(sql) == 0) return Qnil;
299
366
 
300
- rc = sqlite3_prepare(db->sqlite3_db, RSTRING_PTR(sql), RSTRING_LEN(sql), &stmt, 0);
301
- if (rc) {
302
- fprintf(stderr, "Failed to prepare statement: %s\n", sqlite3_errmsg(db->sqlite3_db));
303
- sqlite3_finalize(stmt);
304
- // TODO: raise error
305
- return Qfalse;
306
- }
367
+ GetDatabase(self, db);
307
368
 
369
+ prepare_multi_stmt(db->sqlite3_db, &stmt, sql);
308
370
  bind_all_parameters(stmt, argc, argv);
309
371
  column_count = sqlite3_column_count(stmt);
310
372
  if (column_count != 1)
@@ -315,6 +377,8 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
315
377
  case SQLITE_ROW:
316
378
  value = get_column_value(stmt, 0, sqlite3_column_type(stmt, 0));
317
379
  break;
380
+ case SQLITE_DONE:
381
+ break;
318
382
  case SQLITE_BUSY:
319
383
  rb_raise(cError, "Database is busy");
320
384
  case SQLITE_ERROR:
@@ -354,6 +418,28 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
354
418
  return filename ? rb_str_new_cstr(filename) : Qnil;
355
419
  }
356
420
 
421
+ VALUE Database_transaction_active_p(VALUE self) {
422
+ Database_t *db;
423
+ GetDatabase(self, db);
424
+
425
+ return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
426
+ }
427
+
428
+ VALUE Database_load_extension(VALUE self, VALUE path) {
429
+ Database_t *db;
430
+ GetDatabase(self, db);
431
+ char *err_msg;
432
+
433
+ int rc = sqlite3_load_extension(db->sqlite3_db, RSTRING_PTR(path), 0, &err_msg);
434
+ if (rc != SQLITE_OK) {
435
+ VALUE error = rb_exc_new2(cError, err_msg);
436
+ sqlite3_free(err_msg);
437
+ rb_exc_raise(error);
438
+ }
439
+
440
+ return self;
441
+ }
442
+
357
443
  void Init_Extralite() {
358
444
  VALUE mExtralite = rb_define_module("Extralite");
359
445
  VALUE cDatabase = rb_define_class_under(mExtralite, "Database", rb_cObject);
@@ -364,12 +450,16 @@ void Init_Extralite() {
364
450
  rb_define_method(cDatabase, "query", Database_query_hash, -1);
365
451
  rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
366
452
  rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
453
+ rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
367
454
  rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
368
455
  rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
369
456
 
370
457
  rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
371
458
  rb_define_method(cDatabase, "changes", Database_changes, 0);
372
459
  rb_define_method(cDatabase, "filename", Database_filename, -1);
460
+ rb_define_method(cDatabase, "transaction_active?", Database_transaction_active_p, 0);
461
+ rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
373
462
 
374
463
  cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
464
+ ID_STRIP = rb_intern("strip");
375
465
  }
data/extralite.gemspec CHANGED
@@ -8,11 +8,11 @@ Gem::Specification.new do |s|
8
8
  s.author = 'Sharon Rosner'
9
9
  s.email = 'sharon@noteflakes.com'
10
10
  s.files = `git ls-files`.split
11
- s.homepage = 'https://digital-fabric.github.io/extralite'
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.github.io/extralite/",
15
- "homepage_uri" => "https://digital-fabric.github.io/extralite/",
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"]
@@ -1,3 +1,3 @@
1
1
  module Extralite
2
- VERSION = '0.1'
2
+ VERSION = '0.5'
3
3
  end
data/test/helper.rb ADDED
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/setup'
4
+ require 'extralite'
5
+ require 'minitest/autorun'
6
+ require 'minitest/reporters'
7
+
8
+ Minitest::Reporters.use! [
9
+ Minitest::Reporters::SpecReporter.new
10
+ ]
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class DatabaseTest < MiniTest::Test
6
+ def setup
7
+ @db = Extralite::Database.new('/tmp/extralite.db')
8
+ @db.query('create table if not exists t (x,y,z)')
9
+ @db.query('delete from t')
10
+ @db.query('insert into t values (1, 2, 3)')
11
+ @db.query('insert into t values (4, 5, 6)')
12
+ end
13
+
14
+ def test_database
15
+ r = @db.query('select 1 as foo')
16
+ assert_equal [{foo: 1}], r
17
+ end
18
+
19
+ def test_query
20
+ r = @db.query('select * from t')
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_query_hash
28
+ r = @db.query_hash('select * from t')
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
33
+ end
34
+
35
+ def test_query_ary
36
+ r = @db.query_ary('select * from t')
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
49
+ end
50
+
51
+ def test_query_single_column
52
+ r = @db.query_single_column('select y from t')
53
+ assert_equal [2, 5], r
54
+
55
+ r = @db.query_single_column('select y from t where x = 2')
56
+ assert_equal [], r
57
+ end
58
+
59
+ def test_query_single_value
60
+ r = @db.query_single_value('select z from t order by Z desc limit 1')
61
+ assert_equal 6, r
62
+
63
+ r = @db.query_single_value('select z from t where x = 2')
64
+ assert_nil r
65
+ end
66
+
67
+ def test_transaction_active?
68
+ assert_equal false, @db.transaction_active?
69
+ @db.query('begin')
70
+ assert_equal true, @db.transaction_active?
71
+ @db.query('rollback')
72
+ assert_equal false, @db.transaction_active?
73
+ end
74
+
75
+ def test_multiple_statements
76
+ @db.query("insert into t values ('a', 'b', 'c'); insert into t values ('d', 'e', 'f');")
77
+
78
+ assert_equal [1, 4, 'a', 'd'], @db.query_single_column('select x from t order by x')
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
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.1'
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-21 00:00:00.000000000 Z
11
+ date: 2021-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -102,9 +102,11 @@ extensions:
102
102
  extra_rdoc_files:
103
103
  - README.md
104
104
  files:
105
+ - ".github/workflows/test.yml"
105
106
  - ".gitignore"
106
107
  - CHANGELOG.md
107
108
  - Gemfile
109
+ - Gemfile.lock
108
110
  - LICENSE
109
111
  - README.md
110
112
  - Rakefile
@@ -116,13 +118,15 @@ files:
116
118
  - extralite.gemspec
117
119
  - lib/extralite.rb
118
120
  - lib/extralite/version.rb
119
- homepage: https://digital-fabric.github.io/extralite
121
+ - test/helper.rb
122
+ - test/test_database.rb
123
+ homepage: https://github.com/digital-fabric/extralite
120
124
  licenses:
121
125
  - MIT
122
126
  metadata:
123
127
  source_code_uri: https://github.com/digital-fabric/extralite
124
- documentation_uri: https://digital-fabric.github.io/extralite/
125
- homepage_uri: https://digital-fabric.github.io/extralite/
128
+ documentation_uri: https://github.com/digital-fabric/extralite
129
+ homepage_uri: https://github.com/digital-fabric/extralite
126
130
  changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
127
131
  post_install_message:
128
132
  rdoc_options:
@@ -143,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
143
147
  - !ruby/object:Gem::Version
144
148
  version: '0'
145
149
  requirements: []
146
- rubygems_version: 3.0.8
150
+ rubygems_version: 3.1.4
147
151
  signing_key:
148
152
  specification_version: 4
149
153
  summary: Extra-lightweight SQLite3 wrapper for Ruby