extralite 1.2 → 1.6

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