extralite 1.0 → 1.4

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: 9c69948d51f689ead3e4ccf008bc7b0670085d0c987d39359bb38172b9993b58
4
- data.tar.gz: 776ed4e4f95cdb405b9b3be277d0aaa5a27fcd0e84aff8f6ebb3aeece531b1cf
3
+ metadata.gz: b112a3c34429f8b44c4b4a922c4e038387f6c1db54e6f01377200d7a60324dd4
4
+ data.tar.gz: a664bc81719347079fdfbbffdf2e665bd2772fe8dcf9c30b3ec18c6238a8888a
5
5
  SHA512:
6
- metadata.gz: 472db7ae94e195e647712ce04213538b229bcfebc3f9ec22b3f8e69dceb0a5cbba9000e14147a27ed2e26231aa7c73b43585a45be369f94d8cd2507643dd88b9
7
- data.tar.gz: 6475f99ebe990b9b073f77379f58ddcd4fa0f678fb32e64b39021e3aa7b6d6f9343c8f02d69cce1826a9d156c8b0918985536732af5a11be2bda28524524e8c2
6
+ metadata.gz: '053783bb3f186130fc92b0a57403f0f9472a98e6ce45b1fbb128c5e43914b2a6ec56d39a5e6b10e16f5e6b46f8e9d586837860f63e7538ad238fc0a7aa0995c3'
7
+ data.tar.gz: '058538866f9b2c6a5a0116c8ed3a801aa7bbb8ef8f911eff6d94d7a9cfa98861ad98f4d27e06a736b18c4b62e3c2369a4a306492cc562693da0282363e00f208'
data/CHANGELOG.md CHANGED
@@ -1,3 +1,19 @@
1
+ ## 1.4 2021-08-25
2
+
3
+ - Fix possible segfault in cleanup_stmt
4
+
5
+ ## 1.3 2021-08-17
6
+
7
+ - Pin error classes (for better compatibility with `GC.compact`)
8
+
9
+ ## 1.2 2021-06-06
10
+
11
+ - Add support for big integers
12
+
13
+ ## 1.1 2021-06-02
14
+
15
+ - Add `#close`, `#closed?` methods
16
+
1
17
  ## 1.0 2021-05-27
2
18
 
3
19
  - Refactor C code
data/Gemfile.lock CHANGED
@@ -1,24 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extralite (1.0)
4
+ extralite (1.4)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- ansi (1.5.0)
10
9
  ast (2.4.2)
11
- builder (3.2.4)
12
10
  coderay (1.1.3)
13
11
  docile (1.4.0)
14
12
  json (2.5.1)
15
13
  method_source (1.0.0)
16
14
  minitest (5.14.4)
17
- minitest-reporters (1.4.2)
18
- ansi
19
- builder
20
- minitest (>= 5.0)
21
- ruby-progressbar
22
15
  parallel (1.20.1)
23
16
  parser (3.0.1.1)
24
17
  ast (~> 2.4.1)
@@ -56,7 +49,6 @@ PLATFORMS
56
49
  DEPENDENCIES
57
50
  extralite!
58
51
  minitest (= 5.14.4)
59
- minitest-reporters (= 1.4.2)
60
52
  pry (= 0.13.1)
61
53
  rake-compiler (= 1.1.1)
62
54
  rubocop (= 0.85.1)
data/README.md CHANGED
@@ -1,10 +1,16 @@
1
- ## Extralite
1
+ # Extralite - a Ruby gem for working with SQLite3 databases
2
2
 
3
- Extralite is an extra-lightweight (~365 lines of C-code) SQLite3 wrapper for
3
+ [![Gem Version](https://badge.fury.io/rb/extralite.svg)](http://rubygems.org/gems/extralite)
4
+ [![Modulation Test](https://github.com/digital-fabric/extralite/workflows/Tests/badge.svg)](https://github.com/digital-fabric/extralite/actions?query=workflow%3ATests)
5
+ [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/digital-fabric/extralite/blob/master/LICENSE)
6
+
7
+ ## What is Extralite?
8
+
9
+ Extralite is an extra-lightweight (less than 400 lines of C-code) SQLite3 wrapper for
4
10
  Ruby. It provides a single class with a minimal set of methods to interact with
5
11
  an SQLite3 database.
6
12
 
7
- ### Features
13
+ ## Features
8
14
 
9
15
  - A variety of methods for different data access patterns: row as hash, row as
10
16
  array, single single row, single column, single value.
@@ -17,7 +23,7 @@ an SQLite3 database.
17
23
  - Load extensions (loading of extensions is autmatically enabled. You can find
18
24
  some useful extensions here: https://github.com/nalgeon/sqlean.)
19
25
 
20
- ### Usage
26
+ ## Usage
21
27
 
22
28
  ```ruby
23
29
  require 'extralite'
@@ -65,16 +71,20 @@ db.filename #=> "/tmp/my.db"
65
71
 
66
72
  # load an extension
67
73
  db.load_extension('/path/to/extension.so')
74
+
75
+ # close database
76
+ db.close
77
+ db.closed? #=> true
68
78
  ```
69
79
 
70
- ### Why not just use the sqlite3 gem?
80
+ ## Why not just use the sqlite3 gem?
71
81
 
72
82
  The sqlite3-ruby gem is a popular, solid, well-maintained project, used by
73
83
  thousands of developers. I've been doing a lot of work with SQLite3 lately, and
74
84
  wanted to have a simpler API that gives me query results in a variety of ways.
75
85
  Thus extralite was born.
76
86
 
77
- ### What about concurrency?
87
+ ## What about concurrency?
78
88
 
79
89
  Extralite currently does not release the GVL. This means that even if queries
80
90
  are executed on a separate thread, no other Ruby threads will be scheduled while
@@ -83,7 +93,7 @@ SQLite3 is busy fetching the next record.
83
93
  In the future Extralite might be changed to release the GVL each time
84
94
  `sqlite3_step` is called.
85
95
 
86
- ### Can I use it with an ORM like ActiveRecord or Sequel?
96
+ ## Can I use it with an ORM like ActiveRecord or Sequel?
87
97
 
88
98
  Not yet, but you are welcome to contribute adapters for those projects. I will
89
99
  be releasing my own not-an-ORM tool in the near future.
@@ -39,6 +39,14 @@ static VALUE Database_allocate(VALUE klass) {
39
39
  #define GetDatabase(obj, database) \
40
40
  TypedData_Get_Struct((obj), Database_t, &Database_type, (database))
41
41
 
42
+ // make sure the database is open
43
+ #define GetOpenDatabase(obj, database) { \
44
+ TypedData_Get_Struct((obj), Database_t, &Database_type, (database)); \
45
+ if (!(database)->sqlite3_db) { \
46
+ rb_raise(cError, "Database is closed"); \
47
+ } \
48
+ }
49
+
42
50
 
43
51
  VALUE Database_initialize(VALUE self, VALUE path) {
44
52
  int rc;
@@ -60,12 +68,33 @@ VALUE Database_initialize(VALUE self, VALUE path) {
60
68
  return Qnil;
61
69
  }
62
70
 
71
+ VALUE Database_close(VALUE self) {
72
+ int rc;
73
+ Database_t *db;
74
+ GetDatabase(self, db);
75
+
76
+ rc = sqlite3_close(db->sqlite3_db);
77
+ if (rc) {
78
+ rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
79
+ }
80
+
81
+ db->sqlite3_db = 0;
82
+ return self;
83
+ }
84
+
85
+ VALUE Database_closed_p(VALUE self) {
86
+ Database_t *db;
87
+ GetDatabase(self, db);
88
+
89
+ return db->sqlite3_db ? Qfalse : Qtrue;
90
+ }
91
+
63
92
  inline VALUE get_column_value(sqlite3_stmt *stmt, int col, int type) {
64
93
  switch (type) {
65
94
  case SQLITE_NULL:
66
95
  return Qnil;
67
96
  case SQLITE_INTEGER:
68
- return INT2NUM(sqlite3_column_int(stmt, col));
97
+ return LL2NUM(sqlite3_column_int64(stmt, col));
69
98
  case SQLITE_FLOAT:
70
99
  return DBL2NUM(sqlite3_column_double(stmt, col));
71
100
  case SQLITE_TEXT:
@@ -85,7 +114,7 @@ static inline void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value
85
114
  sqlite3_bind_null(stmt, pos);
86
115
  return;
87
116
  case T_FIXNUM:
88
- sqlite3_bind_int(stmt, pos, NUM2INT(value));
117
+ sqlite3_bind_int64(stmt, pos, NUM2LL(value));
89
118
  return;
90
119
  case T_FLOAT:
91
120
  sqlite3_bind_double(stmt, pos, NUM2DBL(value));
@@ -193,7 +222,7 @@ typedef struct query_ctx {
193
222
 
194
223
  VALUE cleanup_stmt(VALUE arg) {
195
224
  query_ctx *ctx = (query_ctx *)arg;
196
- sqlite3_finalize(ctx->stmt);
225
+ if (ctx->stmt) sqlite3_finalize(ctx->stmt);
197
226
  return Qnil;
198
227
  }
199
228
 
@@ -214,7 +243,7 @@ VALUE safe_query_hash(VALUE arg) {
214
243
  VALUE column_names;
215
244
 
216
245
  check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
217
- GetDatabase(ctx->self, db);
246
+ GetOpenDatabase(ctx->self, db);
218
247
 
219
248
  prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
220
249
  bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
@@ -250,7 +279,7 @@ VALUE safe_query_ary(VALUE arg) {
250
279
  VALUE sql;
251
280
 
252
281
  check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
253
- GetDatabase(ctx->self, db);
282
+ GetOpenDatabase(ctx->self, db);
254
283
 
255
284
  prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
256
285
  bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
@@ -283,7 +312,7 @@ VALUE safe_query_single_row(VALUE arg) {
283
312
  VALUE column_names;
284
313
 
285
314
  check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
286
- GetDatabase(ctx->self, db);
315
+ GetOpenDatabase(ctx->self, db);
287
316
 
288
317
  prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
289
318
  bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
@@ -314,7 +343,7 @@ VALUE safe_query_single_column(VALUE arg) {
314
343
  VALUE value;
315
344
 
316
345
  check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
317
- GetDatabase(ctx->self, db);
346
+ GetOpenDatabase(ctx->self, db);
318
347
 
319
348
  prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
320
349
  bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
@@ -348,7 +377,7 @@ VALUE safe_query_single_value(VALUE arg) {
348
377
  VALUE value = Qnil;
349
378
 
350
379
  check_arity_and_prepare_sql(ctx->argc, ctx->argv, sql);
351
- GetDatabase(ctx->self, db);
380
+ GetOpenDatabase(ctx->self, db);
352
381
 
353
382
  prepare_multi_stmt(db->sqlite3_db, &ctx->stmt, sql);
354
383
  bind_all_parameters(ctx->stmt, ctx->argc, ctx->argv);
@@ -370,14 +399,14 @@ VALUE Database_query_single_value(int argc, VALUE *argv, VALUE self) {
370
399
 
371
400
  VALUE Database_last_insert_rowid(VALUE self) {
372
401
  Database_t *db;
373
- GetDatabase(self, db);
402
+ GetOpenDatabase(self, db);
374
403
 
375
404
  return INT2NUM(sqlite3_last_insert_rowid(db->sqlite3_db));
376
405
  }
377
406
 
378
407
  VALUE Database_changes(VALUE self) {
379
408
  Database_t *db;
380
- GetDatabase(self, db);
409
+ GetOpenDatabase(self, db);
381
410
 
382
411
  return INT2NUM(sqlite3_changes(db->sqlite3_db));
383
412
  }
@@ -386,7 +415,7 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
386
415
  const char *db_name;
387
416
  const char *filename;
388
417
  Database_t *db;
389
- GetDatabase(self, db);
418
+ GetOpenDatabase(self, db);
390
419
 
391
420
  rb_check_arity(argc, 0, 1);
392
421
  db_name = (argc == 1) ? StringValueCStr(argv[0]) : "main";
@@ -396,14 +425,14 @@ VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
396
425
 
397
426
  VALUE Database_transaction_active_p(VALUE self) {
398
427
  Database_t *db;
399
- GetDatabase(self, db);
428
+ GetOpenDatabase(self, db);
400
429
 
401
430
  return sqlite3_get_autocommit(db->sqlite3_db) ? Qfalse : Qtrue;
402
431
  }
403
432
 
404
433
  VALUE Database_load_extension(VALUE self, VALUE path) {
405
434
  Database_t *db;
406
- GetDatabase(self, db);
435
+ GetOpenDatabase(self, db);
407
436
  char *err_msg;
408
437
 
409
438
  int rc = sqlite3_load_extension(db->sqlite3_db, RSTRING_PTR(path), 0, &err_msg);
@@ -422,6 +451,8 @@ void Init_Extralite() {
422
451
  rb_define_alloc_func(cDatabase, Database_allocate);
423
452
 
424
453
  rb_define_method(cDatabase, "initialize", Database_initialize, 1);
454
+ rb_define_method(cDatabase, "close", Database_close, 0);
455
+ rb_define_method(cDatabase, "closed?", Database_closed_p, 0);
425
456
 
426
457
  rb_define_method(cDatabase, "query", Database_query_hash, -1);
427
458
  rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
@@ -439,6 +470,9 @@ void Init_Extralite() {
439
470
  cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
440
471
  cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
441
472
  cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
473
+ rb_gc_register_mark_object(cError);
474
+ rb_gc_register_mark_object(cSQLError);
475
+ rb_gc_register_mark_object(cBusyError);
442
476
 
443
477
  ID_STRIP = rb_intern("strip");
444
478
  }
data/extralite.gemspec CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.add_development_dependency 'rake-compiler', '1.1.1'
25
25
  s.add_development_dependency 'minitest', '5.14.4'
26
- s.add_development_dependency 'minitest-reporters', '1.4.2'
27
26
  s.add_development_dependency 'simplecov', '0.17.1'
28
27
  s.add_development_dependency 'rubocop', '0.85.1'
29
28
  s.add_development_dependency 'pry', '0.13.1'
@@ -1,3 +1,3 @@
1
1
  module Extralite
2
- VERSION = '1.0'
2
+ VERSION = '1.4'
3
3
  end
data/test/helper.rb CHANGED
@@ -3,8 +3,3 @@
3
3
  require 'bundler/setup'
4
4
  require 'extralite'
5
5
  require 'minitest/autorun'
6
- require 'minitest/reporters'
7
-
8
- Minitest::Reporters.use! [
9
- Minitest::Reporters::SpecReporter.new
10
- ]
@@ -89,4 +89,15 @@ end
89
89
  r = @db.query('select 1 as foo; ')
90
90
  assert_equal [{ foo: 1 }], r
91
91
  end
92
+
93
+ def test_close
94
+ assert_equal false, @db.closed?
95
+ r = @db.query_single_value('select 42')
96
+ assert_equal 42, r
97
+
98
+ assert_equal @db, @db.close
99
+ assert_equal true, @db.closed?
100
+
101
+ assert_raises(Extralite::Error) { @db.query_single_value('select 42') }
102
+ end
92
103
  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: '1.0'
4
+ version: '1.4'
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-27 00:00:00.000000000 Z
11
+ date: 2021-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
40
  version: 5.14.4
41
- - !ruby/object:Gem::Dependency
42
- name: minitest-reporters
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '='
46
- - !ruby/object:Gem::Version
47
- version: 1.4.2
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - '='
53
- - !ruby/object:Gem::Version
54
- version: 1.4.2
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: simplecov
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -146,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
132
  - !ruby/object:Gem::Version
147
133
  version: '0'
148
134
  requirements: []
149
- rubygems_version: 3.1.4
135
+ rubygems_version: 3.1.6
150
136
  signing_key:
151
137
  specification_version: 4
152
138
  summary: Extra-lightweight SQLite3 wrapper for Ruby