extralite 2.3 → 2.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.
data/test/issue-38.rb ADDED
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "sqlite3"
4
+ require "./lib/extralite"
5
+ require "benchmark"
6
+
7
+ # Setup
8
+
9
+ File.delete("benchmark.sqlite3") if File.exist?("benchmark.sqlite3")
10
+
11
+ POOL_SIZE = 10
12
+
13
+ EXTRALITE_CONNECTIONS = POOL_SIZE.times.map do
14
+ db = Extralite::Database.new("benchmark.sqlite3")
15
+ db.execute("PRAGMA journal_mode = WAL")
16
+ db.execute("PRAGMA synchronous = NORMAL")
17
+ db.execute("PRAGMA journal_size_limit = 64000000")
18
+ db.execute("PRAGMA mmap_size = 128000000")
19
+ db.execute("PRAGMA cache_size = 2000")
20
+ db.execute("PRAGMA busy_timeout = 5000")
21
+ db
22
+ end
23
+
24
+ SQLITE3_CONNECTIONS = POOL_SIZE.times.map do
25
+ db = SQLite3::Database.new("benchmark.sqlite3")
26
+ db.execute("PRAGMA journal_mode = WAL")
27
+ db.execute("PRAGMA synchronous = NORMAL")
28
+ db.execute("PRAGMA journal_size_limit = 64000000")
29
+ db.execute("PRAGMA mmap_size = 128000000")
30
+ db.execute("PRAGMA cache_size = 2000")
31
+ db.execute("PRAGMA busy_timeout = 5000")
32
+ db
33
+ end
34
+
35
+ EXTRALITE_CONNECTIONS[0].execute("CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, created_at TEXT, updated_at TEXT) STRICT")
36
+ insert_statement = EXTRALITE_CONNECTIONS[0].prepare("INSERT INTO users (name, created_at, updated_at) VALUES (?, ?, ?)")
37
+ 1000.times do
38
+ insert_statement.execute("John Doe", Time.now.iso8601, Time.now.iso8601)
39
+ end
40
+
41
+ # Benchmark variations
42
+
43
+ THREAD_COUNTS = [1, 2, 4, 8]
44
+ LIMITS = [10, 100, 1000]
45
+ CLIENTS = %w[extralite sqlite3]
46
+
47
+ # Benchmark
48
+
49
+ GC.disable
50
+ Benchmark.bm do |x|
51
+ LIMITS.each do |limit|
52
+ THREAD_COUNTS.each do |thread_count|
53
+ CLIENTS.each do |client|
54
+ GC.start
55
+
56
+ x.report("#{client.rjust('extralite'.length)} - limit: #{limit}, threads: #{thread_count}") do
57
+ threads = thread_count.times.map do |thread_number|
58
+ Thread.new do
59
+ start = Time.now
60
+ if client == "extralite"
61
+ 1_000.times do
62
+ records = EXTRALITE_CONNECTIONS[thread_number].query_ary("SELECT * FROM users LIMIT #{limit}")
63
+ raise "Expected #{limit} but got #{length}" unless records.length == limit
64
+ end
65
+ else
66
+ 1_000.times do
67
+ records = SQLITE3_CONNECTIONS[thread_number].query("SELECT * FROM users LIMIT #{limit}").entries
68
+ raise "Expected #{limit} but got #{length}" unless records.length == limit
69
+ end
70
+ end
71
+ end
72
+ end
73
+ threads.each(&:join)
74
+ end
75
+ end
76
+ puts
77
+ end
78
+ end
79
+ end
80
+ GC.enable
data/test/perf_ary.rb CHANGED
@@ -12,15 +12,18 @@ end
12
12
  require 'benchmark/ips'
13
13
  require 'fileutils'
14
14
 
15
- DB_PATH = '/tmp/extralite_sqlite3_perf.db'
15
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
+ puts "DB_PATH = #{DB_PATH.inspect}"
17
+
16
18
 
17
19
  def prepare_database(count)
18
- FileUtils.rm(DB_PATH) rescue nil
19
20
  db = Extralite::Database.new(DB_PATH)
20
- db.query('create table foo ( a integer primary key, b text )')
21
+ db.query('create table if not exists foo ( a integer primary key, b text )')
22
+ db.query('delete from foo')
21
23
  db.query('begin')
22
24
  count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
23
25
  db.query('commit')
26
+ db.close
24
27
  end
25
28
 
26
29
  def sqlite3_run(count)
data/test/perf_hash.rb CHANGED
@@ -12,15 +12,17 @@ end
12
12
  require 'benchmark/ips'
13
13
  require 'fileutils'
14
14
 
15
- DB_PATH = '/tmp/extralite_sqlite3_perf.db'
15
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
+ puts "DB_PATH = #{DB_PATH.inspect}"
16
17
 
17
18
  def prepare_database(count)
18
- FileUtils.rm(DB_PATH) rescue nil
19
19
  db = Extralite::Database.new(DB_PATH)
20
- db.query('create table foo ( a integer primary key, b text )')
20
+ db.query('create table if not exists foo ( a integer primary key, b text )')
21
+ db.query('delete from foo')
21
22
  db.query('begin')
22
23
  count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
23
24
  db.query('commit')
25
+ db.close
24
26
  end
25
27
 
26
28
  def sqlite3_run(count)
@@ -36,7 +38,7 @@ def extralite_run(count)
36
38
  end
37
39
 
38
40
  [10, 1000, 100000].each do |c|
39
- puts; puts; puts "Record count: #{c}"
41
+ puts "Record count: #{c}"
40
42
 
41
43
  prepare_database(c)
42
44
 
@@ -48,4 +50,5 @@ end
48
50
 
49
51
  x.compare!
50
52
  end
53
+ puts; puts;
51
54
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  require_relative 'helper'
4
4
 
5
+ require 'date'
6
+ require 'tempfile'
7
+
5
8
  class DatabaseTest < MiniTest::Test
6
9
  def setup
7
10
  @db = Extralite::Database.new(':memory:')
@@ -123,6 +126,9 @@ end
123
126
 
124
127
  r = @db.query('select x, y, z from t where z = ?', 6)
125
128
  assert_equal [{ x: 4, y: 5, z: 6 }], r
129
+
130
+ error = assert_raises(Extralite::ParameterError) { @db.query_single_value('select ?', Date.today) }
131
+ assert_equal error.message, 'Cannot bind parameter at position 1 of type Date'
126
132
  end
127
133
 
128
134
  def test_parameter_binding_with_index
@@ -152,6 +158,94 @@ end
152
158
  assert_equal [{ x: 4, y: 5, z: 6 }], r
153
159
  end
154
160
 
161
+ class Foo; end
162
+
163
+ def test_parameter_binding_from_hash
164
+ assert_equal 42, @db.query_single_value('select :bar', foo: 41, bar: 42)
165
+ assert_equal 42, @db.query_single_value('select :bar', 'foo' => 41, 'bar' => 42)
166
+ assert_equal 42, @db.query_single_value('select ?8', 7 => 41, 8 => 42)
167
+ assert_nil @db.query_single_value('select :bar', foo: 41)
168
+
169
+ error = assert_raises(Extralite::ParameterError) { @db.query_single_value('select ?', Foo.new => 42) }
170
+ assert_equal error.message, 'Cannot bind parameter with a key of type DatabaseTest::Foo'
171
+
172
+ error = assert_raises(Extralite::ParameterError) { @db.query_single_value('select ?', %w[a b] => 42) }
173
+ assert_equal error.message, 'Cannot bind parameter with a key of type Array'
174
+ end
175
+
176
+ def test_parameter_binding_from_struct
177
+ foo_bar = Struct.new(:":foo", :bar)
178
+ value = foo_bar.new(41, 42)
179
+ assert_equal 41, @db.query_single_value('select :foo', value)
180
+ assert_equal 42, @db.query_single_value('select :bar', value)
181
+ assert_nil @db.query_single_value('select :baz', value)
182
+ end
183
+
184
+ def test_parameter_binding_from_data_class
185
+ skip "Data isn't supported in Ruby < 3.2" if RUBY_VERSION < '3.2'
186
+
187
+ foo_bar = Data.define(:":foo", :bar)
188
+ value = foo_bar.new(":foo": 41, bar: 42)
189
+ assert_equal 42, @db.query_single_value('select :bar', value)
190
+ assert_nil @db.query_single_value('select :baz', value)
191
+ end
192
+
193
+ def test_parameter_binding_for_blobs
194
+ sql = 'SELECT typeof(data) AS type, data FROM blobs WHERE ROWID = ?'
195
+ blob_path = File.expand_path('fixtures/image.png', __dir__)
196
+ @db.execute('CREATE TABLE blobs (data BLOB)')
197
+
198
+ # it's a string, not a blob
199
+ @db.execute('INSERT INTO blobs VALUES (?)', 'Hello, 世界!')
200
+ result = @db.query_single_row(sql, @db.last_insert_rowid)
201
+ assert_equal 'text', result[:type]
202
+ assert_equal Encoding::UTF_8, result[:data].encoding
203
+
204
+ data = File.binread(blob_path)
205
+ @db.execute('INSERT INTO blobs VALUES (?)', data)
206
+ result = @db.query_single_row(sql, @db.last_insert_rowid)
207
+ assert_equal 'blob', result[:type]
208
+ assert_equal data, result[:data]
209
+
210
+ data = (+'Hello, 世界!').force_encoding(Encoding::ASCII_8BIT)
211
+ @db.execute('INSERT INTO blobs VALUES (?)', data)
212
+ result = @db.query_single_row(sql, @db.last_insert_rowid)
213
+ assert_equal 'blob', result[:type]
214
+ assert_equal Encoding::ASCII_8BIT, result[:data].encoding
215
+ assert_equal 'Hello, 世界!', result[:data].force_encoding(Encoding::UTF_8)
216
+
217
+ data = Extralite::Blob.new('Hello, 世界!')
218
+ @db.execute('INSERT INTO blobs VALUES (?)', data)
219
+ result = @db.query_single_row(sql, @db.last_insert_rowid)
220
+ assert_equal 'blob', result[:type]
221
+ assert_equal Encoding::ASCII_8BIT, result[:data].encoding
222
+ assert_equal 'Hello, 世界!', result[:data].force_encoding(Encoding::UTF_8)
223
+ end
224
+
225
+ def test_parameter_binding_for_simple_types
226
+ assert_nil @db.query_single_value('select ?', nil)
227
+
228
+ # 32-bit integers
229
+ assert_equal -2** 31, @db.query_single_value('select ?', -2**31)
230
+ assert_equal 2**31 - 1, @db.query_single_value('select ?', 2**31 - 1)
231
+
232
+ # 64-bit integers
233
+ assert_equal -2 ** 63, @db.query_single_value('select ?', -2 ** 63)
234
+ assert_equal 2**63 - 1, @db.query_single_value('select ?', 2**63 - 1)
235
+
236
+ # floats
237
+ assert_equal Float::MIN, @db.query_single_value('select ?', Float::MIN)
238
+ assert_equal Float::MAX, @db.query_single_value('select ?', Float::MAX)
239
+
240
+ # boolean
241
+ assert_equal 1, @db.query_single_value('select ?', true)
242
+ assert_equal 0, @db.query_single_value('select ?', false)
243
+
244
+ # strings and symbols
245
+ assert_equal 'foo', @db.query_single_value('select ?', 'foo')
246
+ assert_equal 'foo', @db.query_single_value('select ?', :foo)
247
+ end
248
+
155
249
  def test_value_casting
156
250
  r = @db.query_single_value("select 'abc'")
157
251
  assert_equal 'abc', r
@@ -293,7 +387,7 @@ end
293
387
  end
294
388
 
295
389
  def test_database_busy_timeout
296
- fn = "/tmp/extralite-#{rand(10000)}.db"
390
+ fn = Tempfile.new('extralite_test_database_busy_timeout').path
297
391
  db1 = Extralite::Database.new(fn)
298
392
  db2 = Extralite::Database.new(fn)
299
393
 
@@ -388,17 +482,77 @@ end
388
482
  assert_match /^\#\<Extralite::Database:0x[0-9a-f]+ :memory:\>$/, db.inspect
389
483
  end
390
484
 
485
+ def test_database_inspect_on_closed_database
486
+ db = Extralite::Database.new(':memory:')
487
+ assert_match /^\#\<Extralite::Database:0x[0-9a-f]+ :memory:\>$/, db.inspect
488
+ db.close
489
+ assert_match /^\#\<Extralite::Database:0x[0-9a-f]+ \(closed\)\>$/, db.inspect
490
+ end
491
+
391
492
  def test_string_encoding
392
493
  db = Extralite::Database.new(':memory:')
393
494
  v = db.query_single_value("select 'foo'")
394
495
  assert_equal 'foo', v
395
496
  assert_equal 'UTF-8', v.encoding.name
396
497
  end
498
+
499
+ def test_database_transaction_commit
500
+ path = Tempfile.new('extralite_test_database_transaction_commit').path
501
+ db1 = Extralite::Database.new(path)
502
+ db2 = Extralite::Database.new(path)
503
+
504
+ db1.execute('create table foo(x)')
505
+ assert_equal ['foo'], db1.tables
506
+ assert_equal ['foo'], db2.tables
507
+
508
+ q1 = Queue.new
509
+ q2 = Queue.new
510
+ th = Thread.new do
511
+ db1.transaction do
512
+ assert_equal true, db1.transaction_active?
513
+ db1.execute('insert into foo values (42)')
514
+ q1 << true
515
+ q2.pop
516
+ end
517
+ assert_equal false, db1.transaction_active?
518
+ end
519
+ q1.pop
520
+ # transaction not yet committed
521
+ assert_equal false, db2.transaction_active?
522
+ assert_equal [], db2.query('select * from foo')
523
+
524
+ q2 << true
525
+ th.join
526
+ # transaction now committed
527
+ assert_equal [{ x: 42 }], db2.query('select * from foo')
528
+ end
529
+
530
+ def test_database_transaction_rollback
531
+ db = Extralite::Database.new(':memory:')
532
+ db.execute('create table foo(x)')
533
+
534
+ assert_equal [], db.query('select * from foo')
535
+
536
+ exception = nil
537
+ begin
538
+ db.transaction do
539
+ db.execute('insert into foo values (42)')
540
+ raise 'bar'
541
+ end
542
+ rescue => e
543
+ exception = e
544
+ end
545
+
546
+ assert_equal [], db.query('select * from foo')
547
+ assert_kind_of RuntimeError, exception
548
+ assert_equal 'bar', exception.message
549
+ end
397
550
  end
398
551
 
399
552
  class ScenarioTest < MiniTest::Test
400
553
  def setup
401
- @db = Extralite::Database.new('/tmp/extralite.db')
554
+ @fn = Tempfile.new('extralite_scenario_test').path
555
+ @db = Extralite::Database.new(@fn)
402
556
  @db.query('create table if not exists t (x,y,z)')
403
557
  @db.query('delete from t')
404
558
  @db.query('insert into t values (1, 2, 3)')
@@ -408,7 +562,7 @@ class ScenarioTest < MiniTest::Test
408
562
  def test_concurrent_transactions
409
563
  done = false
410
564
  t = Thread.new do
411
- db = Extralite::Database.new('/tmp/extralite.db')
565
+ db = Extralite::Database.new(@fn)
412
566
  db.query 'begin immediate'
413
567
  sleep 0.01 until done
414
568
 
@@ -465,6 +619,7 @@ class ScenarioTest < MiniTest::Test
465
619
  def test_database_trace
466
620
  sqls = []
467
621
  @db.trace { |sql| sqls << sql }
622
+ GC.start
468
623
 
469
624
  @db.query('select 1')
470
625
  assert_equal ['select 1'], sqls
@@ -515,10 +670,107 @@ class BackupTest < MiniTest::Test
515
670
  end
516
671
 
517
672
  def test_backup_with_fn
518
- tmp_fn = "/tmp/#{rand(86400)}.db"
673
+ tmp_fn = Tempfile.new('extralite_test_backup_with_fn').path
519
674
  @src.backup(tmp_fn)
520
675
 
521
676
  db = Extralite::Database.new(tmp_fn)
522
677
  assert_equal [[1, 2, 3], [4, 5, 6]], db.query_ary('select * from t')
523
678
  end
524
679
  end
680
+
681
+ class GVLReleaseThresholdTest < Minitest::Test
682
+ def setup
683
+ @sql = <<~SQL
684
+ WITH RECURSIVE r(i) AS (
685
+ VALUES(0)
686
+ UNION ALL
687
+ SELECT i FROM r
688
+ LIMIT 3000000
689
+ )
690
+ SELECT i FROM r WHERE i = 1;
691
+ SQL
692
+ end
693
+
694
+ def test_default_gvl_release_threshold
695
+ db = Extralite::Database.new(':memory:')
696
+ assert_equal 1000, db.gvl_release_threshold
697
+ end
698
+
699
+ def test_gvl_always_release
700
+ skip if !IS_LINUX
701
+
702
+ delays = []
703
+ running = true
704
+ t1 = Thread.new do
705
+ last = Time.now
706
+ while running
707
+ sleep 0.1
708
+ now = Time.now
709
+ delays << (now - last)
710
+ last = now
711
+ end
712
+ end
713
+ t2 = Thread.new do
714
+ db = Extralite::Database.new(':memory:')
715
+ db.gvl_release_threshold = 1
716
+ db.query(@sql)
717
+ ensure
718
+ running = false
719
+ end
720
+ t2.join
721
+ t1.join
722
+
723
+ assert delays.size > 4
724
+ assert_equal 0, delays.select { |d| d > 0.15 }.size
725
+ end
726
+
727
+ def test_gvl_always_hold
728
+ skip if !IS_LINUX
729
+
730
+ delays = []
731
+ running = true
732
+
733
+ signal = Queue.new
734
+ db = Extralite::Database.new(':memory:')
735
+ db.gvl_release_threshold = 0
736
+
737
+ t1 = Thread.new do
738
+ last = Time.now
739
+ while running
740
+ signal << true
741
+ sleep 0.1
742
+ now = Time.now
743
+ delays << (now - last)
744
+ last = now
745
+ end
746
+ end
747
+
748
+ t2 = Thread.new do
749
+ signal.pop
750
+ db.query(@sql)
751
+ ensure
752
+ running = false
753
+ end
754
+ t2.join
755
+ t1.join
756
+
757
+ assert delays.size >= 1
758
+ assert delays.first > 0.2
759
+ end
760
+
761
+ def test_gvl_mode_get_set
762
+ db = Extralite::Database.new(':memory:')
763
+ assert_equal 1000, db.gvl_release_threshold
764
+
765
+ db.gvl_release_threshold = 42
766
+ assert_equal 42, db.gvl_release_threshold
767
+
768
+ db.gvl_release_threshold = 0
769
+ assert_equal 0, db.gvl_release_threshold
770
+
771
+ assert_raises(ArgumentError) { db.gvl_release_threshold = :foo }
772
+
773
+ db.gvl_release_threshold = nil
774
+ assert_equal 1000, db.gvl_release_threshold
775
+ end
776
+ end
@@ -103,7 +103,8 @@ class IteratorTest < MiniTest::Test
103
103
  end
104
104
 
105
105
  def test_return_from_block_issue_26
106
- db = Extralite::Database.new('/tmp/locked.db')
106
+ fn = Tempfile.new('extralite_test_return_from_block_issue_26').path
107
+ db = Extralite::Database.new(fn)
107
108
 
108
109
  λ = ->(sql) {
109
110
  db.prepare(sql).each { |r| r.each { |_, v| return v } }
data/test/test_query.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'helper'
4
+ require 'date'
4
5
 
5
6
  class QueryTest < MiniTest::Test
6
7
  def setup
@@ -267,7 +268,7 @@ class QueryTest < MiniTest::Test
267
268
  end
268
269
 
269
270
  def test_query_each_without_block
270
- query = @db.prepare('select * from t')
271
+ query = @db.prepare('select * from t')
271
272
  iter = query.each
272
273
  assert_kind_of Extralite::Iterator, iter
273
274
 
@@ -294,7 +295,7 @@ class QueryTest < MiniTest::Test
294
295
  end
295
296
 
296
297
  def test_query_each_ary_without_block
297
- query = @db.prepare('select * from t')
298
+ query = @db.prepare('select * from t')
298
299
  iter = query.each_ary
299
300
  assert_kind_of Extralite::Iterator, iter
300
301
 
@@ -322,7 +323,7 @@ class QueryTest < MiniTest::Test
322
323
  end
323
324
 
324
325
  def test_query_each_single_column_without_block
325
- query = @db.prepare('select x from t')
326
+ query = @db.prepare('select x from t')
326
327
  iter = query.each_single_column
327
328
  assert_kind_of Extralite::Iterator, iter
328
329
 
@@ -375,6 +376,9 @@ class QueryTest < MiniTest::Test
375
376
  def test_query_parameter_binding_simple
376
377
  r = @db.prepare('select x, y, z from t where x = ?').bind(1).next
377
378
  assert_equal({ x: 1, y: 2, z: 3 }, r)
379
+
380
+ error = assert_raises(Extralite::ParameterError) { @db.prepare('select ?').bind(Date.today).next }
381
+ assert_equal error.message, 'Cannot bind parameter at position 1 of type Date'
378
382
  end
379
383
 
380
384
  def test_query_parameter_binding_with_index
@@ -404,6 +408,38 @@ class QueryTest < MiniTest::Test
404
408
  assert_equal({ x: 4, y: 5, z: 6 }, r)
405
409
  end
406
410
 
411
+ class Foo; end
412
+
413
+ def test_parameter_binding_from_hash
414
+ assert_equal 42, @db.prepare('select :bar').bind(foo: 41, bar: 42).next_single_column
415
+ assert_equal 42, @db.prepare('select :bar').bind('foo' => 41, 'bar' => 42).next_single_column
416
+ assert_equal 42, @db.prepare('select ?8').bind(7 => 41, 8 => 42).next_single_column
417
+ assert_nil @db.prepare('select :bar').bind(foo: 41).next_single_column
418
+
419
+ error = assert_raises(Extralite::ParameterError) { @db.prepare('select ?').bind(Foo.new => 42).next_single_column }
420
+ assert_equal error.message, 'Cannot bind parameter with a key of type QueryTest::Foo'
421
+
422
+ error = assert_raises(Extralite::ParameterError) { @db.prepare('select ?').bind(%w[a b] => 42).next_single_column }
423
+ assert_equal error.message, 'Cannot bind parameter with a key of type Array'
424
+ end
425
+
426
+ def test_parameter_binding_from_struct
427
+ foo_bar = Struct.new(:":foo", :bar)
428
+ value = foo_bar.new(41, 42)
429
+ assert_equal 41, @db.prepare('select :foo').bind(value).next_single_column
430
+ assert_equal 42, @db.prepare('select :bar').bind(value).next_single_column
431
+ assert_nil @db.prepare('select :baz').bind(value).next_single_column
432
+ end
433
+
434
+ def test_parameter_binding_from_data_class
435
+ skip "Data isn't supported in Ruby < 3.2" if RUBY_VERSION < '3.2'
436
+
437
+ foo_bar = Data.define(:":foo", :bar)
438
+ value = foo_bar.new(":foo": 41, bar: 42)
439
+ assert_equal 42, @db.prepare('select :bar').bind(value).next_single_column
440
+ assert_nil @db.prepare('select :baz').bind(value).next_single_column
441
+ end
442
+
407
443
  def test_query_columns
408
444
  r = @db.prepare("select 'abc' as a, 'def' as b").columns
409
445
  assert_equal [:a, :b], r
@@ -459,7 +495,7 @@ class QueryTest < MiniTest::Test
459
495
  { a: 1, b: '2', c: 3 },
460
496
  { a: '4', b: 5, c: 6 }
461
497
  ], @db.query('select * from foo')
462
- end
498
+ end
463
499
 
464
500
  def test_query_status
465
501
  assert_equal 0, @query.status(Extralite::SQLITE_STMTSTATUS_RUN)
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: '2.3'
4
+ version: '2.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: 2023-11-12 00:00:00.000000000 Z
11
+ date: 2023-12-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -88,12 +88,14 @@ extensions:
88
88
  extra_rdoc_files:
89
89
  - README.md
90
90
  files:
91
+ - ".editorconfig"
91
92
  - ".github/FUNDING.yml"
92
93
  - ".github/workflows/test.yml"
93
94
  - ".gitignore"
94
95
  - ".yardopts"
95
96
  - CHANGELOG.md
96
97
  - Gemfile
98
+ - Gemfile-bundle
97
99
  - Gemfile.lock
98
100
  - LICENSE
99
101
  - README.md
@@ -118,7 +120,9 @@ files:
118
120
  - lib/sequel/adapters/extralite.rb
119
121
  - test/extensions/text.dylib
120
122
  - test/extensions/text.so
123
+ - test/fixtures/image.png
121
124
  - test/helper.rb
125
+ - test/issue-38.rb
122
126
  - test/perf_ary.rb
123
127
  - test/perf_hash.rb
124
128
  - test/perf_prepared.rb