extralite-bundle 3.1.0 → 3.1.2

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: c98b87050195caee2a3ac6bbbefdd3bf77ed3fe29add59cf18d5162299856d93
4
- data.tar.gz: b0796d7fba1df64d3095d29ff6d8f00bb6f66320467cf54d0ab6f31a164c7c59
3
+ metadata.gz: 9eac653308555c057d121db6b0e17905fff645a62d926bdd3ac07323f40f8f9e
4
+ data.tar.gz: 2bcfeb952ce57afa647b969016891edae0fd615fc78f97a0a6b0336cc35791d6
5
5
  SHA512:
6
- metadata.gz: 34f204b0d4abf91ac7b2f114c2e6838515498a068e750c476c7c473a3823e33f871088974b204aed8e98192c1bcfbdec2f8d5f2df1bff770a523724e662a79b7
7
- data.tar.gz: c6b48bf9540dd37a663ab21db610f6aeee0193a3cf539b5cff8ba600475b15cc91c9e8679f7c0a897af0b227b39f597aa8d2da4b378c6a5c2d8aaf64d6a6dc49
6
+ metadata.gz: aa4d929c51e1f2c05fc0e67aa37447281c50d697b9dff242ca6f96e3723027e03b3db5b4c437399f28045a12d251dfff3e0f3a47709302b132347cca9c7fa514
7
+ data.tar.gz: 9809ca98906d5b853e646814057b976a55171249ae85b0502eea8ab39032d725889d736d3e9eff71ee46c9ca31d64e81f42102936753e69a2714188abec3bca5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ # 3.1.2 2026-10-03
2
+
3
+ - Fix handling of failed BEGIN in #transaction (#89)
4
+ - Reset of cached statements post-query (#88)
5
+ - Add missing wal checkpoint, integrity_check docs to README
6
+ - Implement `Database#integrity_check`, `Database#quick_check`
7
+
8
+ # 3.1.1 2026-09-26
9
+
10
+ - Fix clearing of stmt cache after `DB#close` or after GC (#87)
11
+
1
12
  # 3.1.0 2026-09-22
2
13
 
3
14
  - Update bundled SQLite to 3.53.4
data/Gemfile CHANGED
@@ -1,7 +1,3 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
3
  gemspec name: 'extralite'
4
-
5
- group :development do
6
- gem "ruby_memcheck", "2.3.0" if Gem::Platform.local.os == "linux"
7
- end
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 Sharon Rosner
3
+ Copyright (c) 2026 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
@@ -49,14 +49,14 @@ latest features and enhancements.
49
49
  allowing iterating through single records or batches of records.
50
50
  - [Prepared queries](#prepared-queries).
51
51
  - [Parameter binding](#parameter-binding).
52
- - [Automatic query caching] for queries with parameters.
52
+ - [Automatic query caching](#automatic-query-caching) for parametric queries.
53
53
  - [Batch execution](#batch-execution-of-queries) of queries.
54
54
  - [transactions and savepoints](#transactions-and-savepoints).
55
55
  - Advanced features: load [SQLite extensions](#loading-extensions), create
56
56
  [backups](#creating-backups), retrieve [status
57
57
  information](#retrieving-status-information), work with
58
58
  [changesets](#working-with-changesets), interrogate [database
59
- limits](#working-with-database-limits), [trace](#tracing-sql-statements)
59
+ limits](#working-with-database-limits), [trace](#tracing-sql-statements), [WAL checkpoints](#wal-checkpoints), and run [integrity checks](#integrity-checks).
60
60
  queries.
61
61
  - [Sequel](#usage-with-sequel) adapter.
62
62
 
@@ -363,6 +363,16 @@ To use the transform, pass it along with the SQL string to `Database#query`:
363
363
  db.qurey(transform, sql) #=> [...]
364
364
  ```
365
365
 
366
+ Structured transforms support the following column types:
367
+
368
+ - `integer`
369
+ - `float`
370
+ - `text`
371
+ - `bool` - represented as an integer value of 0/1.
372
+ - `json` - represented as a string (text).
373
+ - A custom proc/lambda - e.g. `->(v) { v.split(',') }`.
374
+ - `auto` - uses the native database data type.
375
+
366
376
  Transforms can also be used with [prepared
367
377
  queries](#transforms-in-prepared-queries).
368
378
 
@@ -1303,6 +1313,31 @@ db.query('select ?, ?', 1, 2)
1303
1313
  # { sql: "select ?, ?", args: [1, 2] }
1304
1314
  ```
1305
1315
 
1316
+ ### WAL Checkpoints
1317
+
1318
+ Exrtralite lets you manually perform a WAL checkpoint in order to truncate the
1319
+ WAL file at any given moment using the `Database#wal_checkpoint` method:
1320
+
1321
+ ```ruby
1322
+ db.wal_checkpoint(:full)
1323
+ ```
1324
+
1325
+ The `#wal_checkpoint` method takes a mode argument, which should be one
1326
+ `:passive`, `:full`, `:restart`, `:truncate`. For a discussion of the different
1327
+ modes, you can refer to the [SQLite
1328
+ documentation](https://sqlite.org/c3ref/wal_checkpoint_v2.html).
1329
+
1330
+ ### Integrity Checks
1331
+
1332
+ Extralite provides two methods for performing integrity checks,
1333
+ `Database#integrity_check` and `Database#quick_check`, which map to the
1334
+ corresponding pragmas. The two methods return an array of error messages. In the
1335
+ case of a normal, uncorrupted database, the methods will return `['ok']`:
1336
+
1337
+ ```ruby
1338
+ db.integrity_check #=> ['ok'] (hopefully)
1339
+ ```
1340
+
1306
1341
  ## Usage with Sequel
1307
1342
 
1308
1343
  Extralite includes an adapter for
data/TODO.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## Remove Query objects
2
+
3
+ - Remove Query
4
+ - Cleanup code
5
+ - Update README
6
+
1
7
  ## Transforms
2
8
 
3
9
  - Add ability to exclude a column:
@@ -226,6 +226,8 @@ static inline void finalize_stmt_ctx(stmt_ctx *ctx) {
226
226
  return;
227
227
  }
228
228
 
229
+ sqlite3_reset(*(ctx->stmtptr));
230
+ sqlite3_clear_bindings(*(ctx->stmtptr));
229
231
  if (!(ctx->flags & STMT_CTX_F_CACHE_HIT))
230
232
  rb_hash_aset(ctx->stmt_cache, ctx->sql, ULONG2NUM((uint64_t)*(ctx->stmtptr)));
231
233
  }
@@ -241,11 +243,7 @@ void make_stmt_ctx(
241
243
 
242
244
  int use_cache = (argc > 0) && (db->flags & DB_F_STMT_CACHE);
243
245
  ctx->flags = use_cache ? STMT_CTX_F_USE_CACHE : 0;
244
- if (use_cache) {
245
- lookup_cache_entry(ctx);
246
- if (ctx->flags & STMT_CTX_F_CACHE_HIT)
247
- sqlite3_clear_bindings(*(ctx->stmtptr));
248
- }
246
+ if (use_cache) lookup_cache_entry(ctx);
249
247
 
250
248
  if (!use_cache || !(*(ctx->stmtptr))) {
251
249
  ctx->str = RSTRING_PTR(sql);
@@ -318,6 +316,7 @@ void *exec_multi_stmt_impl(void *ptr) {
318
316
  int res = sqlite3_prepare_v2(ctx->db, rest, end-rest, &next_stmt, NULL);
319
317
  if (next_stmt) res = SQLITE_MISUSE;
320
318
  if (res != SQLITE_OK) {
319
+ ctx->flags &= ~STMT_CTX_F_USE_CACHE;
321
320
  ctx->rc = res;
322
321
  goto done;
323
322
  }
@@ -367,6 +366,7 @@ int exec_multi_stmt(stmt_ctx *ctx) {
367
366
  if (ctx->rc == SQLITE_OK) return ctx->total_changes;
368
367
 
369
368
  if (*(ctx->stmtptr)) sqlite3_finalize(*(ctx->stmtptr));
369
+
370
370
  return raise_error(ctx);
371
371
  }
372
372
 
@@ -403,6 +403,7 @@ void prep_single_stmt(stmt_ctx *ctx) {
403
403
  if (ctx->rc == SQLITE_OK) return;
404
404
 
405
405
  if (*(ctx->stmtptr)) sqlite3_finalize(*(ctx->stmtptr));
406
+
406
407
  raise_error(ctx);
407
408
  }
408
409
 
@@ -453,12 +454,14 @@ inline int stmt_iterate(query_ctx *ctx) {
453
454
  VALUE cleanup_stmt(query_ctx *ctx) {
454
455
  if (!ctx->stmt) goto done;
455
456
 
456
- if (ctx->flags & STMT_CTX_F_USE_CACHE) {
457
+ if (!(ctx->flags & STMT_CTX_F_USE_CACHE))
458
+ sqlite3_finalize(ctx->stmt);
459
+ else {
460
+ sqlite3_reset(ctx->stmt);
461
+ sqlite3_clear_bindings(ctx->stmt);
457
462
  if (!(ctx->flags & STMT_CTX_F_CACHE_HIT))
458
463
  rb_hash_aset(ctx->db->stmt_cache, ctx->sql, ULONG2NUM((uint64_t)(ctx->stmt)));
459
464
  }
460
- else
461
- sqlite3_finalize(ctx->stmt);
462
465
  done:
463
466
  return Qnil;
464
467
  }
@@ -600,8 +603,6 @@ VALUE run_transform_no_identity(
600
603
  static inline VALUE run_transform(
601
604
  VALUE identity_storage, struct transform_node *node, sqlite3_stmt *stmt
602
605
  ) {
603
- // fprintf(stdout, "transform_container: %p flags: %02x identity_idx: %d\n", node, node->flags, node->identity_idx);
604
- // if (node->flags & TRANSFORM_F_NAME) INSPECT(" name", node->name);
605
606
  if (node->identity_node) {
606
607
  return run_transform_with_identity(identity_storage, node, stmt);
607
608
  }
@@ -72,9 +72,26 @@ static void Database_compact(void *ptr) {
72
72
  db->progress_handler.proc = rb_gc_location(db->progress_handler.proc);
73
73
  }
74
74
 
75
+ static int stmt_cache_iter(VALUE key, VALUE value, VALUE _param) {
76
+ sqlite3_stmt *stmt = (sqlite3_stmt *)NUM2ULONG(value);
77
+ sqlite3_finalize(stmt);
78
+ return ST_CONTINUE;
79
+ }
80
+
81
+ static void stmt_cache_finalize(sqlite3 *db, VALUE stmt_cache) {
82
+ if (stmt_cache == Qnil) return;
83
+ if (rb_hash_size_num(stmt_cache) == 0) return;
84
+
85
+ rb_hash_foreach(stmt_cache, stmt_cache_iter, Qnil);
86
+ RB_GC_GUARD(stmt_cache);
87
+ }
88
+
75
89
  static void Database_free(void *ptr) {
76
90
  Database_t *db = ptr;
77
- if (db->sqlite3_db) sqlite3_close_v2(db->sqlite3_db);
91
+ if (db->sqlite3_db) {
92
+ stmt_cache_finalize(db->sqlite3_db, db->stmt_cache);
93
+ sqlite3_close_v2(db->sqlite3_db);
94
+ }
78
95
  free(ptr);
79
96
  }
80
97
 
@@ -261,6 +278,8 @@ VALUE Database_close(VALUE self) {
261
278
  int rc;
262
279
  Database_t *db = self_to_database(self);
263
280
 
281
+ stmt_cache_finalize(db->sqlite3_db, db->stmt_cache);
282
+ rb_hash_clear(db->stmt_cache);
264
283
  rc = sqlite3_close_v2(db->sqlite3_db);
265
284
  if (rc) {
266
285
  rb_raise(cError, "%s", sqlite3_errmsg(db->sqlite3_db));
@@ -573,13 +592,14 @@ VALUE Database_batch_execute(VALUE self, VALUE sql, VALUE parameters) {
573
592
  if (RSTRING_LEN(sql) == 0) return Qnil;
574
593
 
575
594
  stmt_ctx stmt_ctx;
576
- make_stmt_ctx(&stmt_ctx, db, &stmt, sql, RARRAY_LEN(parameters), NULL);
595
+ make_stmt_ctx(&stmt_ctx, db, &stmt, sql, 1, NULL);
577
596
  prep_single_stmt(&stmt_ctx);
578
597
  // prepare_xsingle_stmt(DB_GVL_MODE(db), db->stmt_cache, db->sqlite3_db, &stmt, sql, 0, NULL);
579
598
  query_ctx ctx = QUERY_CTX(
580
599
  self, sql, db, stmt, parameters,
581
600
  Qnil, QUERY_HASH, ROW_MULTI, ALL_ROWS
582
601
  );
602
+ ctx.flags = stmt_ctx.flags;
583
603
 
584
604
  return rb_ensure(SAFE(safe_batch_execute), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
585
605
  }
@@ -1545,11 +1565,11 @@ int checkpoint_mode_symbol_to_int(VALUE mode) {
1545
1565
  *
1546
1566
  * @overload wal_checkpoint(mode)
1547
1567
  * @param mode [Symbol] checkpoint mode (`:passive`, `:full`, `:restart`, `:truncate`)
1548
- * @return [Array<int>] total and checkpointed frame count
1568
+ * @return [Array<Integer>] total and checkpointed frame count
1549
1569
  * @overload wal_checkpoint(mode, db_name)
1550
1570
  * @param mode [Symbol] checkpoint mode (`:passive`, `:full`, `:restart`, `:truncate`)
1551
1571
  * @param db_name [String] attached database name
1552
- * @return [Array<int>] total and checkpointed frame count
1572
+ * @return [Array<Integer>] total and checkpointed frame count
1553
1573
  */
1554
1574
  VALUE Database_wal_checkpoint(int argc, VALUE *argv, VALUE self) {
1555
1575
  Database_t *db = self_to_open_database(self);
data/gemspec.rb CHANGED
@@ -19,7 +19,7 @@ def common_spec(s)
19
19
 
20
20
  s.add_development_dependency 'rake-compiler', '1.3.1'
21
21
  s.add_development_dependency 'minitest'
22
- s.add_development_dependency 'simplecov', '0.22.0'
23
- s.add_development_dependency 'yard', '0.9.38'
24
- s.add_development_dependency 'sequel', '5.105.0'
22
+ s.add_development_dependency 'simplecov'
23
+ s.add_development_dependency 'yard'
24
+ s.add_development_dependency 'sequel', '5.108.0'
25
25
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Extralite
4
- VERSION = '3.1.0'
4
+ VERSION = '3.1.2'
5
5
  end
data/lib/extralite.rb CHANGED
@@ -215,6 +215,29 @@ module Extralite
215
215
  value.is_a?(Hash) ? pragma_set(value) : pragma_get(value)
216
216
  end
217
217
 
218
+ # Performs a low-level formatting and consistency check of the database
219
+ # using PRAGMA integrity_check. See:
220
+ # https://www.sqlite.org/pragma.html#pragma_integrity_check
221
+ #
222
+ # @param v [Integer, String, nil] max errors or table name
223
+ # @return [Array<String>] array of error strings or 'ok'
224
+ def integrity_check(v = nil)
225
+ query_splat(
226
+ v ? "pragma integrity_check(#{v})" : 'pragma integrity_check'
227
+ )
228
+ end
229
+
230
+ # Performs a quicker integrity check of the database using PRAGMA
231
+ # quick_check. See: https://www.sqlite.org/pragma.html#pragma_quick_check
232
+ #
233
+ # @param v [Integer, String, nil] max errors or table name
234
+ # @return [Array<String>] array of error strings or 'ok'
235
+ def quick_check(v = nil)
236
+ query_splat(
237
+ v ? "pragma quick_check(#{v})" : 'pragma quick_check'
238
+ )
239
+ end
240
+
218
241
  # Error class used to roll back a transaction without propagating an
219
242
  # exception.
220
243
  class Rollback < Error
@@ -237,12 +260,13 @@ module Extralite
237
260
  def transaction(mode = :immediate)
238
261
  abort = false
239
262
  execute "begin #{mode} transaction"
263
+ started = true
240
264
  yield self
241
265
  rescue => e
242
266
  abort = true
243
267
  e.is_a?(Rollback) ? nil : raise
244
268
  ensure
245
- execute(abort ? 'rollback' : 'commit')
269
+ execute(abort ? 'rollback' : 'commit') if started
246
270
  end
247
271
 
248
272
  # Creates a savepoint with the given name. For more information on
data/test/helper.rb CHANGED
@@ -16,3 +16,13 @@ module Minitest::Assertions
16
16
  assert exp_range.include?(act), msg
17
17
  end
18
18
  end
19
+
20
+ module TestExtensions
21
+ def teardown
22
+ @db = nil
23
+ GC.start
24
+ super
25
+ end
26
+ end
27
+
28
+ Minitest::Test.prepend(TestExtensions)
@@ -372,6 +372,86 @@ class DatabaseTest < Minitest::Test
372
372
  # assert_equal 1, @db.pragma('foreign_keys')
373
373
  end
374
374
 
375
+ def test_integrity_check_ok
376
+ r = @db.integrity_check
377
+ assert_equal ['ok'], r
378
+ end
379
+
380
+ def test_integrity_check_bad_var
381
+ assert_raises(Extralite::Error) { @db.integrity_check('foobar') }
382
+ end
383
+
384
+ def test_integrity_check_damaged
385
+ fn = Tempfile.new('extralite_test_integrity_check_damaged').path
386
+ db = Extralite::Database.new(fn)
387
+
388
+ db.execute <<~SQL
389
+ create table foo (x);
390
+ SQL
391
+
392
+ db.batch_execute("insert into foo values (?)", 1..100)
393
+
394
+ assert_equal (1..100).to_a, db.query_splat('select * from foo')
395
+ db.close
396
+
397
+ File.open(fn, 'r+b') do |f|
398
+ 1.times do
399
+ f.seek(8015)
400
+ f.write('\x00' * 16)
401
+ end
402
+ end
403
+
404
+ db = Extralite::Database.new(fn, legacy: true)
405
+ assert_raises(Extralite::Error) { db.query_splat('select * from foo') }
406
+ r = db.integrity_check
407
+ assert_equal 2, r.size
408
+ assert_equal 'database disk image is malformed', r[1]
409
+
410
+ r = db.integrity_check(1)
411
+ assert_equal 1, r.size
412
+ assert_match /^\*\*\* in database main \*\*\*/, r[0]
413
+ end
414
+
415
+ def test_quick_check_ok
416
+ r = @db.quick_check
417
+ assert_equal ['ok'], r
418
+ end
419
+
420
+ def test_quick_check_bad_var
421
+ assert_raises(Extralite::Error) { @db.quick_check('foobar') }
422
+ end
423
+
424
+ def test_quick_check_damaged
425
+ fn = Tempfile.new('extralite_test_quick_check_damaged').path
426
+ db = Extralite::Database.new(fn)
427
+
428
+ db.execute <<~SQL
429
+ create table foo (x);
430
+ SQL
431
+
432
+ db.batch_execute("insert into foo values (?)", 1..100)
433
+
434
+ assert_equal (1..100).to_a, db.query_splat('select * from foo')
435
+ db.close
436
+
437
+ File.open(fn, 'r+b') do |f|
438
+ 1.times do
439
+ f.seek(8015)
440
+ f.write('\x00' * 16)
441
+ end
442
+ end
443
+
444
+ db = Extralite::Database.new(fn, legacy: true)
445
+ assert_raises(Extralite::Error) { db.query_splat('select * from foo') }
446
+ r = db.quick_check
447
+ assert_equal 2, r.size
448
+ assert_equal 'database disk image is malformed', r[1]
449
+
450
+ r = db.integrity_check(1)
451
+ assert_equal 1, r.size
452
+ assert_match /^\*\*\* in database main \*\*\*/, r[0]
453
+ end
454
+
375
455
  def test_execute
376
456
  changes = @db.execute('update t set x = 42')
377
457
  assert_equal 2, changes
@@ -2225,4 +2305,70 @@ class StmtCacheText < Minitest::Test
2225
2305
  assert_equal [{ x: 42 }], rows
2226
2306
  assert_equal({}, @db.stmt_cache)
2227
2307
  end
2308
+
2309
+ def test_stmt_cache_close
2310
+ fn = Tempfile.new('extralite_test_stmt_cache_close').path
2311
+
2312
+ db = Extralite::Database.new(fn)
2313
+ db.query('create table t (x)')
2314
+
2315
+ db.execute <<~SQL
2316
+ insert into t values (42)
2317
+ SQL
2318
+ assert File.file?("#{fn}-wal"), "WAL file should exist"
2319
+
2320
+ assert_equal [{x: 42}], db.query('select * from t where x = ?', 42)
2321
+
2322
+ db.close
2323
+ refute File.file?("#{fn}-wal"), "WAL file should not exist after close"
2324
+ end
2325
+
2326
+ def test_stmt_cache_gc
2327
+ fn = Tempfile.new('extralite_test_stmt_cache_gc').path
2328
+
2329
+ db = Extralite::Database.new(fn)
2330
+ db.query('create table t (x)')
2331
+
2332
+ db.execute <<~SQL
2333
+ insert into t values (42)
2334
+ SQL
2335
+ assert File.file?("#{fn}-wal"), "WAL file should exist"
2336
+
2337
+ assert_equal [{x: 42}], db.query('select * from t where x = ?', 42)
2338
+
2339
+ db = nil
2340
+ GC.start
2341
+ refute File.file?("#{fn}-wal"), "WAL file should not exist after GC"
2342
+ end
2343
+
2344
+ def test_stmt_cache_concurrent_access
2345
+ # https://github.com/digital-fabric/extralite/issues/88
2346
+ fn = Tempfile.new('extralite_test_stmt_cache_concurrent_access').path
2347
+
2348
+ a = Extralite::Database.new(fn)
2349
+ a.execute("pragma journal_mode=wal")
2350
+ a.execute("create table t (id integer primary key, x)")
2351
+ a.execute("insert into t (x) values (1)")
2352
+ a.query_single("select * from t where id = ?", 1)
2353
+
2354
+ b = Extralite::Database.new(fn)
2355
+ b.execute("insert into t (x) values (2)")
2356
+
2357
+ assert_equal 2, b.query_single_splat("select count(*) from t")
2358
+ assert_equal 2, a.query_single_splat("select count(*) from t")
2359
+ end
2360
+
2361
+ def test_stmt_cache_concurrent_transactions
2362
+ # https://github.com/digital-fabric/extralite/issues/89
2363
+ fn = Tempfile.new('extralite_test_stmt_cache_concurrent_access').path
2364
+
2365
+ a = Extralite::Database.new(fn)
2366
+ a.execute('create table t (x)')
2367
+ b = Extralite::Database.new(fn)
2368
+ b.execute('begin immediate transaction')
2369
+
2370
+ assert_raises(Extralite::BusyError) {
2371
+ a.transaction { a.execute("insert into t values (1)") }
2372
+ }
2373
+ end
2228
2374
  end
data/test/test_sequel.rb CHANGED
@@ -20,6 +20,7 @@ class SequelExtraliteTest < Minitest::Test
20
20
 
21
21
  def teardown
22
22
  @db.disconnect
23
+ super
23
24
  end
24
25
 
25
26
  def test_sequel
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: extralite-bundle
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.0
4
+ version: 3.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
@@ -41,44 +41,44 @@ dependencies:
41
41
  name: simplecov
42
42
  requirement: !ruby/object:Gem::Requirement
43
43
  requirements:
44
- - - '='
44
+ - - ">="
45
45
  - !ruby/object:Gem::Version
46
- version: 0.22.0
46
+ version: '0'
47
47
  type: :development
48
48
  prerelease: false
49
49
  version_requirements: !ruby/object:Gem::Requirement
50
50
  requirements:
51
- - - '='
51
+ - - ">="
52
52
  - !ruby/object:Gem::Version
53
- version: 0.22.0
53
+ version: '0'
54
54
  - !ruby/object:Gem::Dependency
55
55
  name: yard
56
56
  requirement: !ruby/object:Gem::Requirement
57
57
  requirements:
58
- - - '='
58
+ - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.9.38
60
+ version: '0'
61
61
  type: :development
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
- - - '='
65
+ - - ">="
66
66
  - !ruby/object:Gem::Version
67
- version: 0.9.38
67
+ version: '0'
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: sequel
70
70
  requirement: !ruby/object:Gem::Requirement
71
71
  requirements:
72
72
  - - '='
73
73
  - !ruby/object:Gem::Version
74
- version: 5.105.0
74
+ version: 5.108.0
75
75
  type: :development
76
76
  prerelease: false
77
77
  version_requirements: !ruby/object:Gem::Requirement
78
78
  requirements:
79
79
  - - '='
80
80
  - !ruby/object:Gem::Version
81
- version: 5.105.0
81
+ version: 5.108.0
82
82
  email: sharon@noteflakes.com
83
83
  executables: []
84
84
  extensions: