extralite 1.0 → 1.4

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: 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