extralite 1.2 → 1.6

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: a6bb308b421895a192cdbc83d022e105ec1fbd4060d8f8898a71f9f13741bd18
4
- data.tar.gz: b044f3d91692b19f7c0cc5912896cec1458c3101ebb5f058fe09c147a3cf00ea
3
+ metadata.gz: e2924788672c7c3960a5baeaeacf14d297cfe461cfb1d20db828d7a67b5536c8
4
+ data.tar.gz: fb4da5551c3b1ddca95ef05520eee477bfb7a29383b9c7e5f5c0638392eba3e9
5
5
  SHA512:
6
- metadata.gz: 4bb40f58b77290b083466563465232cc3aadfa8cb68d305d08edc7fd4b1344d256af45f84f7efe8765fe00b604010a071b5966fd15abb63896b7d843337ce683
7
- data.tar.gz: b29ee3ff34f307d9f45515971ecd0b147fe236f6c2d95e4b48cdd1a91b3d9847d477fee2c667836f83db5c68f559a0f4f2129d12b8d5d1fe5f075ca2cdd6d05c
6
+ metadata.gz: 63b73c0d05cb294b75d79bef5c1362e2c422f16b0e7ae76c3d2b577af20f612007a4fe272942958b38d545efabe4d975c1a0475ee8dec4a68e957d61800ffca7
7
+ data.tar.gz: b79c50cb5c696cf1eb505bbd126b197f1160f56af70e669cfc432e2e16d5423848c139ff9e942fb26c06c3d15f94e1a43f22ab4c317dae4fb0c2290f8d431aa6
data/CHANGELOG.md CHANGED
@@ -1,3 +1,20 @@
1
+ ## 1.6 2021-12-13
2
+
3
+ - Release GVL while fetching rows
4
+
5
+ ## 1.5 2021-12-13
6
+
7
+ - Release GVL while preparing statements
8
+ - Use `sqlite3_prepare_v2` instead of deprecated `sqlite_prepare`
9
+
10
+ ## 1.4 2021-08-25
11
+
12
+ - Fix possible segfault in cleanup_stmt
13
+
14
+ ## 1.3 2021-08-17
15
+
16
+ - Pin error classes (for better compatibility with `GC.compact`)
17
+
1
18
  ## 1.2 2021-06-06
2
19
 
3
20
  - Add support for big integers
data/Gemfile.lock CHANGED
@@ -1,24 +1,17 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- extralite (1.2)
4
+ extralite (1.6)
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
@@ -6,18 +6,23 @@
6
6
 
7
7
  ## What is Extralite?
8
8
 
9
- Extralite is an extra-lightweight (less than 400 lines of C-code) SQLite3 wrapper for
10
- Ruby. It provides a single class with a minimal set of methods to interact with
11
- an SQLite3 database.
9
+ Extralite is an extra-lightweight (less than 430 lines of C-code) SQLite3
10
+ wrapper for Ruby. It provides a single class with a minimal set of methods to
11
+ interact with an SQLite3 database.
12
12
 
13
13
  ## Features
14
14
 
15
- - A variety of methods for different data access patterns: row as hash, row as
16
- array, single single row, single column, single value.
15
+ - A variety of methods for different data access patterns: rows as hashes, rows
16
+ as arrays, single row, single column, single value.
17
+ - Super fast - [up to 12.5x faster](#performance) than the
18
+ [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) gem (see also
19
+ [comparison](#why-not-just-use-the-sqlite3-gem).)
20
+ - Improved [concurrency](#concurrency) for multithreaded apps: the Ruby GVL is
21
+ released while preparing SQL statements and while iterating over results.
17
22
  - Iterate over records with a block, or collect records into an array.
18
23
  - Parameter binding.
19
- - Correctly execute strings with multiple semicolon-separated queries (handy for
20
- creating/modifying schemas).
24
+ - Automatically execute SQL strings containing multiple semicolon-separated
25
+ queries (handy for creating/modifying schemas).
21
26
  - Get last insert rowid.
22
27
  - Get number of rows changed by last query.
23
28
  - Load extensions (loading of extensions is autmatically enabled. You can find
@@ -80,20 +85,55 @@ db.closed? #=> true
80
85
  ## Why not just use the sqlite3 gem?
81
86
 
82
87
  The sqlite3-ruby gem is a popular, solid, well-maintained project, used by
83
- thousands of developers. I've been doing a lot of work with SQLite3 lately, and
84
- wanted to have a simpler API that gives me query results in a variety of ways.
85
- Thus extralite was born.
88
+ thousands of developers. I've been doing a lot of work with SQLite3 databases
89
+ lately, and wanted to have a simpler API that gives me query results in a
90
+ variety of ways. Thus extralite was born.
91
+
92
+ Here's a table summarizing the differences between the two gems:
93
+
94
+ | |sqlite3-ruby|Extralite|
95
+ |-|-|-|
96
+ |API design|multiple classes|single class|
97
+ |Query results|row as hash, row as array, single row, single value|row as hash, row as array, single column, single row, single value|
98
+ |execute multiple statements|separate API (#execute_batch)|integrated|
99
+ |custom functions in Ruby|yes|no|
100
+ |custom collations|yes|no|
101
+ |custom aggregate functions|yes|no|
102
+ |Multithread friendly|no|[yes](#concurrency)|
103
+ |Code size|~2650LoC|~500LoC|
104
+ |Performance|1x|1.5x to 12.5x (see [below](#performance))|
86
105
 
87
106
  ## What about concurrency?
88
107
 
89
- Extralite currently does not release the GVL. This means that even if queries
90
- are executed on a separate thread, no other Ruby threads will be scheduled while
91
- SQLite3 is busy fetching the next record.
108
+ Extralite releases the GVL while making blocking calls to the sqlite3 library,
109
+ that is while preparing SQL statements and fetching rows. Releasing the GVL
110
+ allows other threads to run while the sqlite3 library is busy compiling SQL into
111
+ bytecode, or fetching the next row. This does not seem to hurt Extralite's
112
+ performance:
92
113
 
93
- In the future Extralite might be changed to release the GVL each time
94
- `sqlite3_step` is called.
114
+ ## Performance
115
+
116
+ A benchmark script is
117
+ [included](https://github.com/digital-fabric/extralite/blob/main/test/perf.rb),
118
+ creating a table of various row counts, then fetching the entire table using
119
+ either `sqlite3` or `extralite`. This benchmark shows Extralite to be up to 12.5
120
+ times faster than `sqlite3` when fetching a large number of rows. Here are the
121
+ results (using the `sqlite3` gem performance as baseline):
122
+
123
+ |Row count|sqlite3-ruby (baseline)|Extralite (relative - rounded)|
124
+ |-:|-:|-:|
125
+ |10|1x|1.5x|
126
+ |1K|1x|7x|
127
+ |100K|1x|12.5x|
128
+
129
+ (If you're interested in checking this yourself, just run the script and let me
130
+ know if your results are different.)
95
131
 
96
132
  ## Can I use it with an ORM like ActiveRecord or Sequel?
97
133
 
98
- Not yet, but you are welcome to contribute adapters for those projects. I will
99
- be releasing my own not-an-ORM tool in the near future.
134
+ Not yet, but you are welcome to contribute adapters for those projects.
135
+
136
+ ## Contributing
137
+
138
+ Contributions in the form of issues, PRs or comments will be greatly
139
+ appreciated!
@@ -1,5 +1,6 @@
1
1
  #include <stdio.h>
2
2
  #include "ruby.h"
3
+ #include "ruby/thread.h"
3
4
  #include <sqlite3.h>
4
5
 
5
6
  VALUE cError;
@@ -109,7 +110,7 @@ inline VALUE get_column_value(sqlite3_stmt *stmt, int col, int type) {
109
110
  }
110
111
 
111
112
  static inline void bind_parameter_value(sqlite3_stmt *stmt, int pos, VALUE value) {
112
- switch (TYPE(value)) {
113
+ switch (TYPE(value)) {
113
114
  case T_NIL:
114
115
  sqlite3_bind_null(stmt, pos);
115
116
  return;
@@ -143,7 +144,7 @@ static inline void bind_all_parameters(sqlite3_stmt *stmt, int argc, VALUE *argv
143
144
 
144
145
  static inline VALUE get_column_names(sqlite3_stmt *stmt, int column_count) {
145
146
  VALUE arr = rb_ary_new2(column_count);
146
- for (int i = 0; i < column_count; i++) {
147
+ for (int i = 0; i < column_count; i++) {
147
148
  VALUE name = ID2SYM(rb_intern(sqlite3_column_name(stmt, i)));
148
149
  rb_ary_push(arr, name);
149
150
  }
@@ -168,36 +169,80 @@ static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
168
169
  return row;
169
170
  }
170
171
 
171
- inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
172
- const char *rest = 0;
173
- const char *ptr = RSTRING_PTR(sql);
174
- const char *end = ptr + RSTRING_LEN(sql);
172
+ struct multi_stmt_ctx {
173
+ sqlite3 *db;
174
+ sqlite3_stmt **stmt;
175
+ const char *str;
176
+ int len;
177
+ int rc;
178
+ };
179
+
180
+ void *prepare_multi_stmt_without_gvl(void *ptr) {
181
+ struct multi_stmt_ctx *ctx = (struct multi_stmt_ctx *)ptr;
182
+ const char *rest = NULL;
183
+ const char *str = ctx->str;
184
+ const char *end = ctx->str + ctx->len;
175
185
  while (1) {
176
- int rc = sqlite3_prepare(db, ptr, end - ptr, stmt, &rest);
177
- if (rc) {
178
- sqlite3_finalize(*stmt);
179
- rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
186
+ ctx->rc = sqlite3_prepare_v2(ctx->db, str, end - str, ctx->stmt, &rest);
187
+ if (ctx->rc) {
188
+ sqlite3_finalize(*ctx->stmt);
189
+ return NULL;
180
190
  }
181
191
 
182
- if (rest == end) return;
183
-
192
+ if (rest == end) return NULL;
193
+
184
194
  // perform current query, but discard its results
185
- rc = sqlite3_step(*stmt);
186
- sqlite3_finalize(*stmt);
187
- switch (rc) {
195
+ ctx->rc = sqlite3_step(*ctx->stmt);
196
+ sqlite3_finalize(*ctx->stmt);
197
+ switch (ctx->rc) {
188
198
  case SQLITE_BUSY:
189
- rb_raise(cBusyError, "Database is busy");
190
199
  case SQLITE_ERROR:
191
- rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
200
+ case SQLITE_MISUSE:
201
+ return NULL;
192
202
  }
193
- ptr = rest;
203
+ str = rest;
194
204
  }
205
+ return NULL;
195
206
  }
196
207
 
197
- inline int stmt_iterate(sqlite3_stmt *stmt, sqlite3 *db) {
208
+ /*
209
+ This function prepares a statement from an SQL string containing one or more SQL
210
+ statements. It will release the GVL while the statements are being prepared and
211
+ executed. All statements excluding the last one are executed. The last statement
212
+ is not executed, but instead handed back to the caller for looping over results.
213
+ */
214
+ inline void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
215
+ struct multi_stmt_ctx ctx = {db, stmt, RSTRING_PTR(sql), RSTRING_LEN(sql), 0};
216
+ rb_thread_call_without_gvl(prepare_multi_stmt_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
217
+ RB_GC_GUARD(sql);
218
+
219
+ switch (ctx.rc) {
220
+ case 0:
221
+ return;
222
+ case SQLITE_BUSY:
223
+ rb_raise(cBusyError, "Database is busy");
224
+ case SQLITE_ERROR:
225
+ rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
226
+ default:
227
+ rb_raise(cError, "Invalid return code for prepare_multi_stmt_without_gvl: %d (please open an issue on https://github.com/digital-fabric/extralite)", ctx.rc);
228
+ }
229
+ }
230
+
231
+ struct step_ctx {
232
+ sqlite3_stmt *stmt;
198
233
  int rc;
199
- rc = sqlite3_step(stmt);
200
- switch (rc) {
234
+ };
235
+
236
+ void *stmt_iterate_without_gvl(void *ptr) {
237
+ struct step_ctx *ctx = (struct step_ctx *)ptr;
238
+ ctx->rc = sqlite3_step(ctx->stmt);
239
+ return NULL;
240
+ }
241
+
242
+ inline int stmt_iterate(sqlite3_stmt *stmt, sqlite3 *db) {
243
+ struct step_ctx ctx = {stmt, 0};
244
+ rb_thread_call_without_gvl(stmt_iterate_without_gvl, (void *)&ctx, RUBY_UBF_IO, 0);
245
+ switch (ctx.rc) {
201
246
  case SQLITE_ROW:
202
247
  return 1;
203
248
  case SQLITE_DONE:
@@ -207,7 +252,7 @@ inline int stmt_iterate(sqlite3_stmt *stmt, sqlite3 *db) {
207
252
  case SQLITE_ERROR:
208
253
  rb_raise(cSQLError, "%s", sqlite3_errmsg(db));
209
254
  default:
210
- rb_raise(cError, "Invalid return code for sqlite3_step: %d", rc);
255
+ rb_raise(cError, "Invalid return code for sqlite3_step: %d (please open an issue on https://github.com/digital-fabric/extralite)", ctx.rc);
211
256
  }
212
257
 
213
258
  return 0;
@@ -222,7 +267,7 @@ typedef struct query_ctx {
222
267
 
223
268
  VALUE cleanup_stmt(VALUE arg) {
224
269
  query_ctx *ctx = (query_ctx *)arg;
225
- sqlite3_finalize(ctx->stmt);
270
+ if (ctx->stmt) sqlite3_finalize(ctx->stmt);
226
271
  return Qnil;
227
272
  }
228
273
 
@@ -292,7 +337,7 @@ VALUE safe_query_ary(VALUE arg) {
292
337
  row = row_to_ary(ctx->stmt, column_count);
293
338
  if (yield_to_block) rb_yield(row); else rb_ary_push(result, row);
294
339
  }
295
-
340
+
296
341
  RB_GC_GUARD(row);
297
342
  RB_GC_GUARD(result);
298
343
  return result;
@@ -453,14 +498,14 @@ void Init_Extralite() {
453
498
  rb_define_method(cDatabase, "initialize", Database_initialize, 1);
454
499
  rb_define_method(cDatabase, "close", Database_close, 0);
455
500
  rb_define_method(cDatabase, "closed?", Database_closed_p, 0);
456
-
501
+
457
502
  rb_define_method(cDatabase, "query", Database_query_hash, -1);
458
503
  rb_define_method(cDatabase, "query_hash", Database_query_hash, -1);
459
504
  rb_define_method(cDatabase, "query_ary", Database_query_ary, -1);
460
505
  rb_define_method(cDatabase, "query_single_row", Database_query_single_row, -1);
461
506
  rb_define_method(cDatabase, "query_single_column", Database_query_single_column, -1);
462
507
  rb_define_method(cDatabase, "query_single_value", Database_query_single_value, -1);
463
-
508
+
464
509
  rb_define_method(cDatabase, "last_insert_rowid", Database_last_insert_rowid, 0);
465
510
  rb_define_method(cDatabase, "changes", Database_changes, 0);
466
511
  rb_define_method(cDatabase, "filename", Database_filename, -1);
@@ -470,6 +515,9 @@ void Init_Extralite() {
470
515
  cError = rb_define_class_under(mExtralite, "Error", rb_eRuntimeError);
471
516
  cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
472
517
  cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
518
+ rb_gc_register_mark_object(cError);
519
+ rb_gc_register_mark_object(cSQLError);
520
+ rb_gc_register_mark_object(cBusyError);
473
521
 
474
522
  ID_STRIP = rb_intern("strip");
475
523
  }
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.2'
2
+ VERSION = '1.6'
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
- ]
data/test/perf.rb ADDED
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'sqlite3'
8
+ gem 'extralite', path: '..'
9
+ gem 'benchmark-ips'
10
+ end
11
+
12
+ require 'benchmark/ips'
13
+ require 'fileutils'
14
+
15
+ DB_PATH = '/tmp/extralite_sqlite3_perf.db'
16
+
17
+ def prepare_database(count)
18
+ FileUtils.rm(DB_PATH) rescue nil
19
+ db = Extralite::Database.new(DB_PATH)
20
+ db.query('create table foo ( a integer primary key, b text )')
21
+ db.query('begin')
22
+ count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
23
+ db.query('commit')
24
+ end
25
+
26
+ def sqlite3_run(count)
27
+ db = SQLite3::Database.new(DB_PATH, :results_as_hash => true)
28
+ results = db.execute('select * from foo')
29
+ raise unless results.size == count
30
+ end
31
+
32
+ def extralite_run(count)
33
+ db = Extralite::Database.new(DB_PATH)
34
+ results = db.query('select * from foo')
35
+ raise unless results.size == count
36
+ end
37
+
38
+ [10, 1000, 100000].each do |c|
39
+ puts; puts; puts "Record count: #{c}"
40
+
41
+ prepare_database(c)
42
+
43
+ Benchmark.ips do |x|
44
+ x.config(:time => 3, :warmup => 1)
45
+
46
+ x.report("sqlite3") { sqlite3_run(c) }
47
+ x.report("extralite") { extralite_run(c) }
48
+
49
+ x.compare!
50
+ end
51
+ end
@@ -4,7 +4,7 @@ require_relative 'helper'
4
4
 
5
5
  class DatabaseTest < MiniTest::Test
6
6
  def setup
7
- @db = Extralite::Database.new('/tmp/extralite.db')
7
+ @db = Extralite::Database.new(':memory:')
8
8
  @db.query('create table if not exists t (x,y,z)')
9
9
  @db.query('delete from t')
10
10
  @db.query('insert into t values (1, 2, 3)')
@@ -55,7 +55,7 @@ class DatabaseTest < MiniTest::Test
55
55
  def test_query_single_column
56
56
  r = @db.query_single_column('select y from t')
57
57
  assert_equal [2, 5], r
58
-
58
+
59
59
  r = @db.query_single_column('select y from t where x = 2')
60
60
  assert_equal [], r
61
61
  end
@@ -82,6 +82,17 @@ end
82
82
  assert_equal [1, 4, 'a', 'd'], @db.query_single_column('select x from t order by x')
83
83
  end
84
84
 
85
+ def test_multiple_statements_with_error
86
+ error = nil
87
+ begin
88
+ @db.query("insert into t values foo; insert into t values ('d', 'e', 'f');")
89
+ rescue => error
90
+ end
91
+
92
+ assert_kind_of Extralite::SQLError, error
93
+ assert_equal 'near "foo": syntax error', error.message
94
+ end
95
+
85
96
  def test_empty_sql
86
97
  r = @db.query(' ')
87
98
  assert_nil r
@@ -97,7 +108,75 @@ end
97
108
 
98
109
  assert_equal @db, @db.close
99
110
  assert_equal true, @db.closed?
100
-
111
+
101
112
  assert_raises(Extralite::Error) { @db.query_single_value('select 42') }
102
113
  end
103
114
  end
115
+
116
+ class ScenarioTest < MiniTest::Test
117
+ def setup
118
+ @db = Extralite::Database.new('/tmp/extralite.db')
119
+ @db.query('create table if not exists t (x,y,z)')
120
+ @db.query('delete from t')
121
+ @db.query('insert into t values (1, 2, 3)')
122
+ @db.query('insert into t values (4, 5, 6)')
123
+ end
124
+
125
+ def test_concurrent_transactions
126
+ done = false
127
+ t = Thread.new do
128
+ db = Extralite::Database.new('/tmp/extralite.db')
129
+ db.query 'begin immediate'
130
+ sleep 0.01 until done
131
+
132
+ while true
133
+ begin
134
+ db.query 'commit'
135
+ break
136
+ rescue Extralite::BusyError
137
+ sleep 0.01
138
+ end
139
+ end
140
+ end
141
+
142
+ sleep 0.1
143
+ @db.query 'begin deferred'
144
+ result = @db.query_single_column('select x from t')
145
+ assert_equal [1, 4], result
146
+
147
+ assert_raises(Extralite::BusyError) do
148
+ @db.query('insert into t values (7, 8, 9)')
149
+ end
150
+
151
+ done = true
152
+ sleep 0.1
153
+
154
+ assert_raises(Extralite::BusyError) do
155
+ @db.query('insert into t values (7, 8, 9)')
156
+ end
157
+
158
+ assert_equal true, @db.transaction_active?
159
+
160
+ # the thing to do in this case is to commit the read transaction, allowing
161
+ # the other thread to commit its write transaction, and then we can
162
+ # "upgrade" to a write transaction
163
+
164
+ @db.query('commit')
165
+
166
+ while true
167
+ begin
168
+ @db.query('begin immediate')
169
+ break
170
+ rescue Extralite::BusyError
171
+ sleep 0.1
172
+ end
173
+ end
174
+
175
+ @db.query('insert into t values (7, 8, 9)')
176
+ @db.query('commit')
177
+
178
+ result = @db.query_single_column('select x from t')
179
+ assert_equal [1, 4, 7], result
180
+ end
181
+ end
182
+
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.2'
4
+ version: '1.6'
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-06-06 00:00:00.000000000 Z
11
+ date: 2021-12-13 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
@@ -118,6 +104,7 @@ files:
118
104
  - lib/extralite.rb
119
105
  - lib/extralite/version.rb
120
106
  - test/helper.rb
107
+ - test/perf.rb
121
108
  - test/test_database.rb
122
109
  homepage: https://github.com/digital-fabric/extralite
123
110
  licenses:
@@ -146,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
133
  - !ruby/object:Gem::Version
147
134
  version: '0'
148
135
  requirements: []
149
- rubygems_version: 3.1.4
136
+ rubygems_version: 3.1.6
150
137
  signing_key:
151
138
  specification_version: 4
152
139
  summary: Extra-lightweight SQLite3 wrapper for Ruby