extralite 2.4 → 2.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.
data/test/perf_hash.rb CHANGED
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Run on Ruby 3.3 with YJIT enabled
4
+
3
5
  require 'bundler/inline'
4
6
 
5
7
  gemfile do
@@ -15,40 +17,40 @@ require 'fileutils'
15
17
  DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
18
  puts "DB_PATH = #{DB_PATH.inspect}"
17
19
 
20
+ $sqlite3_db = SQLite3::Database.new(DB_PATH, results_as_hash: true)
21
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
22
+
18
23
  def prepare_database(count)
19
- db = Extralite::Database.new(DB_PATH)
20
- db.query('create table if not exists foo ( a integer primary key, b text )')
21
- db.query('delete from foo')
22
- db.query('begin')
23
- count.times { db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
24
- db.query('commit')
25
- db.close
24
+ $extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
25
+ $extralite_db.query('delete from foo')
26
+ $extralite_db.query('begin')
27
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
28
+ $extralite_db.query('commit')
26
29
  end
27
30
 
28
31
  def sqlite3_run(count)
29
- db = SQLite3::Database.new(DB_PATH, :results_as_hash => true)
30
- results = db.execute('select * from foo')
32
+ results = $sqlite3_db.execute('select * from foo')
31
33
  raise unless results.size == count
32
34
  end
33
35
 
34
36
  def extralite_run(count)
35
- db = Extralite::Database.new(DB_PATH)
36
- results = db.query('select * from foo')
37
+ results = $extralite_db.query('select * from foo')
37
38
  raise unless results.size == count
38
39
  end
39
40
 
40
41
  [10, 1000, 100000].each do |c|
41
42
  puts "Record count: #{c}"
42
-
43
43
  prepare_database(c)
44
44
 
45
- Benchmark.ips do |x|
46
- x.config(:time => 3, :warmup => 1)
45
+ bm = Benchmark.ips do |x|
46
+ x.config(:time => 5, :warmup => 2)
47
47
 
48
48
  x.report("sqlite3") { sqlite3_run(c) }
49
49
  x.report("extralite") { extralite_run(c) }
50
50
 
51
51
  x.compare!
52
52
  end
53
- puts; puts;
53
+ puts;
54
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
55
+ puts;
54
56
  end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/inline'
4
+
5
+ gemfile do
6
+ source 'https://rubygems.org'
7
+ gem 'extralite', path: '..'
8
+ gem 'sqlite3'
9
+ gem 'benchmark-ips'
10
+ end
11
+
12
+ require 'benchmark/ips'
13
+ require 'fileutils'
14
+
15
+ DB_PATH = "/tmp/extralite_sqlite3_perf-#{Time.now.to_i}-#{rand(10000)}.db"
16
+ puts "DB_PATH = #{DB_PATH.inspect}"
17
+
18
+ def prepare_database(count)
19
+ $sqlite3_db = SQLite3::Database.new(DB_PATH, results_as_hash: true)
20
+ $extralite_db = Extralite::Database.new(DB_PATH, gvl_release_threshold: -1)
21
+
22
+ $extralite_db.query('create table if not exists foo ( a integer primary key, b text )')
23
+ $extralite_db.query('delete from foo')
24
+ $extralite_db.query('begin')
25
+ count.times { $extralite_db.query('insert into foo (b) values (?)', "hello#{rand(1000)}" )}
26
+ $extralite_db.query('commit')
27
+
28
+ $sqlite3_stmt = $sqlite3_db.prepare('select * from foo')
29
+ $extralite_q = $extralite_db.prepare('select * from foo')
30
+ end
31
+
32
+ def sqlite3_run(count)
33
+ results = $sqlite3_stmt.execute
34
+ raise unless results.to_a.size == count
35
+ end
36
+
37
+ def extralite_run(count)
38
+ results = $extralite_q.to_a
39
+ raise unless results.size == count
40
+ end
41
+
42
+ [10, 1000, 100000].each do |c|
43
+ puts "Record count: #{c}"
44
+
45
+ prepare_database(c)
46
+
47
+ bm = Benchmark.ips do |x|
48
+ x.config(:time => 5, :warmup => 2)
49
+
50
+ x.report("sqlite3") { sqlite3_run(c) }
51
+ x.report("extralite") { extralite_run(c) }
52
+
53
+ x.compare!
54
+ end
55
+ puts;
56
+ bm.entries.each { |e| puts "#{e.label}: #{(e.ips * c).round.to_i} rows/s" }
57
+ puts;
58
+ end
@@ -0,0 +1,161 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ require 'date'
6
+ require 'tempfile'
7
+
8
+ class ChangesetTest < MiniTest::Test
9
+ def setup
10
+ @db = Extralite::Database.new(':memory:')
11
+ skip if !@db.respond_to?(:track_changes)
12
+
13
+ @db.execute('create table if not exists t (x integer primary key, y, z)')
14
+ end
15
+
16
+ def test_each
17
+ changeset = Extralite::Changeset.new
18
+
19
+ changeset.track(@db, [nil]) do
20
+ @db.execute('insert into t values (1, 2, 3)')
21
+ end
22
+ changes = []
23
+ changeset.each { |*o| changes << o }
24
+ assert_equal [
25
+ [:insert, 't', nil, [1, 2, 3]]
26
+ ], changes
27
+
28
+
29
+ changeset.track(@db, [nil]) do
30
+ @db.execute('update t set y = 22 where x = 1')
31
+ end
32
+ changes = []
33
+ changeset.each { |*o| changes << o }
34
+ assert_equal [
35
+ [:update, 't', [1, 2, nil], [nil, 22, nil]]
36
+ ], changes
37
+
38
+
39
+ changeset.track(@db, [nil]) do
40
+ @db.execute('delete from t where x = 1')
41
+ end
42
+ changes = []
43
+ changeset.each { |*o| changes << o }
44
+ assert_equal [
45
+ [:delete, 't', [1, 22, 3], nil]
46
+ ], changes
47
+ end
48
+
49
+ def test_to_a
50
+ changeset = Extralite::Changeset.new
51
+
52
+ changeset.track(@db, [nil]) do
53
+ @db.execute('insert into t values (1, 2, 3)')
54
+ @db.execute('insert into t values (4, 5, 6)')
55
+ end
56
+ assert_equal [
57
+ [:insert, 't', nil, [1, 2, 3]],
58
+ [:insert, 't', nil, [4, 5, 6]]
59
+ ], changeset.to_a
60
+
61
+
62
+ changeset.track(@db, [nil]) do
63
+ @db.execute('update t set y = 22.22 where z < 10')
64
+ end
65
+ assert_equal [
66
+ [:update, 't', [1, 2, nil], [nil, 22.22, nil]],
67
+ [:update, 't', [4, 5, nil], [nil, 22.22, nil]]
68
+ ], changeset.to_a
69
+
70
+
71
+ changeset.track(@db, [nil]) do
72
+ @db.execute('delete from t where x = 1')
73
+ end
74
+ assert_equal [
75
+ [:delete, 't', [1, 22.22, 3], nil]
76
+ ], changeset.to_a
77
+ end
78
+
79
+ def test_apply
80
+ changeset = Extralite::Changeset.new
81
+
82
+ changeset.track(@db, [:t]) do
83
+ @db.execute('insert into t values (1, 2, 3)')
84
+ @db.execute('insert into t values (4, 5, 6)')
85
+ end
86
+
87
+ db2 = Extralite::Database.new(':memory:')
88
+ db2.execute('create table if not exists t (x integer primary key, y, z)')
89
+
90
+ changeset.apply(db2)
91
+
92
+ assert_equal [
93
+ { x: 1, y: 2, z: 3 },
94
+ { x: 4, y: 5, z: 6 }
95
+ ], db2.query('select * from t')
96
+ end
97
+
98
+ def test_invert
99
+ changeset = Extralite::Changeset.new
100
+
101
+ changeset.track(@db, [:t]) do
102
+ @db.execute('insert into t values (1, 2, 3)')
103
+ @db.execute('insert into t values (4, 5, 6)')
104
+ end
105
+
106
+ db2 = Extralite::Database.new(':memory:')
107
+ db2.execute('create table if not exists t (x integer primary key, y, z)')
108
+
109
+ changeset.apply(db2)
110
+
111
+ assert_equal [
112
+ { x: 1, y: 2, z: 3 },
113
+ { x: 4, y: 5, z: 6 }
114
+ ], db2.query('select * from t')
115
+
116
+ db2.execute('insert into t values (7, 8, 9)')
117
+ inverted = changeset.invert
118
+
119
+ assert_kind_of Extralite::Changeset, inverted
120
+ refute_equal inverted, changeset
121
+
122
+ assert_equal [
123
+ [:delete, 't', [1, 2, 3], nil],
124
+ [:delete, 't', [4, 5, 6], nil],
125
+ ], inverted.to_a
126
+
127
+ inverted.apply(@db)
128
+ assert_equal [], @db.query('select * from t')
129
+ end
130
+
131
+ def test_blob
132
+ changeset = Extralite::Changeset.new
133
+ assert_equal "", changeset.to_blob
134
+
135
+ changeset.track(@db, [:t]) do
136
+ @db.execute('insert into t values (1, 2, 3)')
137
+ @db.execute('insert into t values (4, 5, 6)')
138
+ end
139
+
140
+ blob = changeset.to_blob
141
+ assert_kind_of String, blob
142
+ assert_equal Encoding::ASCII_8BIT, blob.encoding
143
+ assert !blob.empty?
144
+
145
+ c2 = Extralite::Changeset.new
146
+ c2.load(blob)
147
+ assert_equal c2.to_blob, blob
148
+
149
+ assert_equal [
150
+ [:insert, 't', nil, [1, 2, 3]],
151
+ [:insert, 't', nil, [4, 5, 6]]
152
+ ], c2.to_a
153
+ end
154
+
155
+ def test_empty_blob
156
+ changeset = Extralite::Changeset.new
157
+ changeset.load('')
158
+
159
+ assert_raises(Extralite::Error) { changeset.to_a }
160
+ end
161
+ end