extralite 0.1 → 0.5

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