extralite-bundle 1.14

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.
@@ -0,0 +1,247 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class DatabaseTest < MiniTest::Test
6
+ def setup
7
+ @db = Extralite::Database.new(':memory:')
8
+ @db.query('create table if not exists t (x,y,z)')
9
+ @db.query('delete from t')
10
+ @db.query('insert into t values (1, 2, 3)')
11
+ @db.query('insert into t values (4, 5, 6)')
12
+ end
13
+
14
+ def test_database
15
+ r = @db.query('select 1 as foo')
16
+ assert_equal [{foo: 1}], r
17
+ end
18
+
19
+ def test_query
20
+ r = @db.query('select * from t')
21
+ assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
22
+
23
+ r = @db.query('select * from t where x = 2')
24
+ assert_equal [], r
25
+ end
26
+
27
+ def test_invalid_query
28
+ assert_raises(Extralite::SQLError) { @db.query('blah') }
29
+ end
30
+
31
+ def test_query_hash
32
+ r = @db.query_hash('select * from t')
33
+ assert_equal [{x: 1, y: 2, z: 3}, {x: 4, y: 5, z: 6}], r
34
+
35
+ r = @db.query_hash('select * from t where x = 2')
36
+ assert_equal [], r
37
+ end
38
+
39
+ def test_query_ary
40
+ r = @db.query_ary('select * from t')
41
+ assert_equal [[1, 2, 3], [4, 5, 6]], r
42
+
43
+ r = @db.query_ary('select * from t where x = 2')
44
+ assert_equal [], r
45
+ end
46
+
47
+ def test_query_single_row
48
+ r = @db.query_single_row('select * from t order by x desc limit 1')
49
+ assert_equal({ x: 4, y: 5, z: 6 }, r)
50
+
51
+ r = @db.query_single_row('select * from t where x = 2')
52
+ assert_nil r
53
+ end
54
+
55
+ def test_query_single_column
56
+ r = @db.query_single_column('select y from t')
57
+ assert_equal [2, 5], r
58
+
59
+ r = @db.query_single_column('select y from t where x = 2')
60
+ assert_equal [], r
61
+ end
62
+
63
+ def test_query_single_value
64
+ r = @db.query_single_value('select z from t order by Z desc limit 1')
65
+ assert_equal 6, r
66
+
67
+ r = @db.query_single_value('select z from t where x = 2')
68
+ assert_nil r
69
+ end
70
+
71
+ def test_transaction_active?
72
+ assert_equal false, @db.transaction_active?
73
+ @db.query('begin')
74
+ assert_equal true, @db.transaction_active?
75
+ @db.query('rollback')
76
+ assert_equal false, @db.transaction_active?
77
+ end
78
+
79
+ def test_multiple_statements
80
+ @db.query("insert into t values ('a', 'b', 'c'); insert into t values ('d', 'e', 'f');")
81
+
82
+ assert_equal [1, 4, 'a', 'd'], @db.query_single_column('select x from t order by x')
83
+ end
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
+
96
+ def test_empty_sql
97
+ r = @db.query(' ')
98
+ assert_nil r
99
+
100
+ r = @db.query('select 1 as foo; ')
101
+ assert_equal [{ foo: 1 }], r
102
+ end
103
+
104
+ def test_close
105
+ assert_equal false, @db.closed?
106
+ r = @db.query_single_value('select 42')
107
+ assert_equal 42, r
108
+
109
+ assert_equal @db, @db.close
110
+ assert_equal true, @db.closed?
111
+
112
+ assert_raises(Extralite::Error) { @db.query_single_value('select 42') }
113
+ end
114
+
115
+ def test_parameter_binding_simple
116
+ r = @db.query('select x, y, z from t where x = ?', 1)
117
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
118
+
119
+ r = @db.query('select x, y, z from t where z = ?', 6)
120
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
121
+ end
122
+
123
+ def test_parameter_binding_with_index
124
+ r = @db.query('select x, y, z from t where x = ?2', 0, 1)
125
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
126
+
127
+ r = @db.query('select x, y, z from t where z = ?3', 3, 4, 6)
128
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
129
+ end
130
+
131
+ def test_parameter_binding_with_name
132
+ r = @db.query('select x, y, z from t where x = :x', x: 1, y: 2)
133
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
134
+
135
+ r = @db.query('select x, y, z from t where z = :zzz', 'zzz' => 6)
136
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
137
+
138
+ r = @db.query('select x, y, z from t where z = :bazzz', ':bazzz' => 6)
139
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
140
+ end
141
+
142
+ def test_parameter_binding_with_index_key
143
+ r = @db.query('select x, y, z from t where z = ?', 1 => 3)
144
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
145
+
146
+ r = @db.query('select x, y, z from t where x = ?2', 1 => 42, 2 => 4)
147
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
148
+ end
149
+
150
+ def test_value_casting
151
+ r = @db.query_single_value("select 'abc'")
152
+ assert_equal 'abc', r
153
+
154
+ r = @db.query_single_value('select 123')
155
+ assert_equal 123, r
156
+
157
+ r = @db.query_single_value('select 12.34')
158
+ assert_equal 12.34, r
159
+
160
+ r = @db.query_single_value('select zeroblob(4)')
161
+ assert_equal "\x00\x00\x00\x00", r
162
+
163
+ r = @db.query_single_value('select null')
164
+ assert_nil r
165
+ end
166
+
167
+
168
+
169
+ def test_extension_loading
170
+ case RUBY_PLATFORM
171
+ when /linux/
172
+ @db.load_extension(File.join(__dir__, 'extensions/text.so'))
173
+ when /darwin/
174
+ @db.load_extension(File.join(__dir__, 'extensions/text.dylib'))
175
+ end
176
+
177
+ r = @db.query_single_value("select reverse('abcd')")
178
+ assert_equal 'dcba', r
179
+ end
180
+ end
181
+
182
+ class ScenarioTest < MiniTest::Test
183
+ def setup
184
+ @db = Extralite::Database.new('/tmp/extralite.db')
185
+ @db.query('create table if not exists t (x,y,z)')
186
+ @db.query('delete from t')
187
+ @db.query('insert into t values (1, 2, 3)')
188
+ @db.query('insert into t values (4, 5, 6)')
189
+ end
190
+
191
+ def test_concurrent_transactions
192
+ done = false
193
+ t = Thread.new do
194
+ db = Extralite::Database.new('/tmp/extralite.db')
195
+ db.query 'begin immediate'
196
+ sleep 0.01 until done
197
+
198
+ while true
199
+ begin
200
+ db.query 'commit'
201
+ break
202
+ rescue Extralite::BusyError
203
+ sleep 0.01
204
+ end
205
+ end
206
+ end
207
+
208
+ sleep 0.1
209
+ @db.query 'begin deferred'
210
+ result = @db.query_single_column('select x from t')
211
+ assert_equal [1, 4], result
212
+
213
+ assert_raises(Extralite::BusyError) do
214
+ @db.query('insert into t values (7, 8, 9)')
215
+ end
216
+
217
+ done = true
218
+ sleep 0.1
219
+
220
+ assert_raises(Extralite::BusyError) do
221
+ @db.query('insert into t values (7, 8, 9)')
222
+ end
223
+
224
+ assert_equal true, @db.transaction_active?
225
+
226
+ # the thing to do in this case is to commit the read transaction, allowing
227
+ # the other thread to commit its write transaction, and then we can
228
+ # "upgrade" to a write transaction
229
+
230
+ @db.query('commit')
231
+
232
+ while true
233
+ begin
234
+ @db.query('begin immediate')
235
+ break
236
+ rescue Extralite::BusyError
237
+ sleep 0.1
238
+ end
239
+ end
240
+
241
+ @db.query('insert into t values (7, 8, 9)')
242
+ @db.query('commit')
243
+
244
+ result = @db.query_single_column('select x from t')
245
+ assert_equal [1, 4, 7], result
246
+ end
247
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class ExtraliteTest < MiniTest::Test
6
+ def test_sqlite3_version
7
+ assert_match /^3\.\d+\.\d+$/, Extralite.sqlite3_version
8
+ end
9
+ end
@@ -0,0 +1,165 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class PreparedStatementTest < MiniTest::Test
6
+ def setup
7
+ @db = Extralite::Database.new(':memory:')
8
+ @db.query('create table if not exists t (x,y,z)')
9
+ @db.query('delete from t')
10
+ @db.query('insert into t values (1, 2, 3)')
11
+ @db.query('insert into t values (4, 5, 6)')
12
+
13
+ @stmt = @db.prepare('select * from t where x = ?')
14
+ end
15
+
16
+ # def test_foo
17
+ # stmt = @db.prepare('select 1')
18
+ # assert_equal 1, stmt.query_single_value
19
+ # end
20
+
21
+ def test_prepared_statement_props
22
+ assert_kind_of Extralite::PreparedStatement, @stmt
23
+ assert_equal @db, @stmt.database
24
+ assert_equal @db, @stmt.db
25
+ assert_equal 'select * from t where x = ?', @stmt.sql
26
+ end
27
+
28
+ def test_prepared_statement_query
29
+ assert_equal [{ x: 1, y: 2, z: 3 }], @stmt.query(1)
30
+
31
+ buf = []
32
+ @stmt.query(1) { |r| buf << r }
33
+ assert_equal [{ x: 1, y: 2, z: 3 }], buf
34
+ end
35
+
36
+ def test_prepared_statement_with_invalid_sql
37
+ assert_raises(Extralite::SQLError) { @db.prepare('blah') }
38
+ end
39
+
40
+ def test_prepared_statement_query_hash
41
+ r = @stmt.query_hash(4)
42
+ assert_equal [{x: 4, y: 5, z: 6}], r
43
+
44
+ r = @stmt.query_hash(5)
45
+ assert_equal [], r
46
+ end
47
+
48
+ def test_prepared_statement_query_ary
49
+ r = @stmt.query_ary(1)
50
+ assert_equal [[1, 2, 3]], r
51
+
52
+ r = @stmt.query_ary(2)
53
+ assert_equal [], r
54
+ end
55
+
56
+ def test_prepared_statement_query_single_row
57
+ r = @stmt.query_single_row(4)
58
+ assert_equal({ x: 4, y: 5, z: 6 }, r)
59
+
60
+ r = @stmt.query_single_row(5)
61
+ assert_nil r
62
+ end
63
+
64
+ def test_prepared_statement_query_single_column
65
+ stmt =
66
+ r = @db.prepare('select y from t').query_single_column
67
+ assert_equal [2, 5], r
68
+
69
+ r = @db.prepare('select y from t where x = 2').query_single_column
70
+ assert_equal [], r
71
+ end
72
+
73
+ def test_prepared_statement_query_single_value
74
+ r = @db.prepare('select z from t order by Z desc limit 1').query_single_value
75
+ assert_equal 6, r
76
+
77
+ r = @db.prepare('select z from t where x = 2').query_single_value
78
+ assert_nil r
79
+ end
80
+
81
+ def test_prepared_statement_multiple_statements
82
+ assert_raises(Extralite::Error) {
83
+ @db.prepare("insert into t values ('a', 'b', 'c'); insert into t values ('d', 'e', 'f');")
84
+ }
85
+ end
86
+
87
+ def test_prepared_statement_multiple_statements_with_bad_sql
88
+ error = nil
89
+ begin
90
+ stmt =@db.prepare("insert into t values foo; insert into t values ('d', 'e', 'f');")
91
+ stmt.query
92
+ rescue => error
93
+ end
94
+
95
+ assert_kind_of Extralite::SQLError, error
96
+ assert_equal 'near "foo": syntax error', error.message
97
+ end
98
+
99
+ def test_prepared_statement_repeated_execution_missing_param
100
+ r = @stmt.query_hash(4)
101
+ assert_equal [{x: 4, y: 5, z: 6}], r
102
+
103
+ r = @stmt.query_hash
104
+ assert_equal [], r
105
+ end
106
+
107
+ def test_prepared_statement_empty_sql
108
+ assert_raises(Extralite::Error) { @db.prepare(' ') }
109
+
110
+ r = @db.prepare('select 1 as foo; ').query
111
+ assert_equal [{ foo: 1 }], r
112
+ end
113
+
114
+ def test_prepared_statement_parameter_binding_simple
115
+ r = @db.prepare('select x, y, z from t where x = ?').query(1)
116
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
117
+
118
+ r = @db.prepare('select x, y, z from t where z = ?').query(6)
119
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
120
+ end
121
+
122
+ def test_prepared_statement_parameter_binding_with_index
123
+ r = @db.prepare('select x, y, z from t where x = ?2').query(0, 1)
124
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
125
+
126
+ r = @db.prepare('select x, y, z from t where z = ?3').query(3, 4, 6)
127
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
128
+ end
129
+
130
+ def test_prepared_statement_parameter_binding_with_name
131
+ r = @db.prepare('select x, y, z from t where x = :x').query(x: 1, y: 2)
132
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
133
+
134
+ r = @db.prepare('select x, y, z from t where z = :zzz').query('zzz' => 6)
135
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
136
+
137
+ r = @db.prepare('select x, y, z from t where z = :bazzz').query(':bazzz' => 6)
138
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
139
+ end
140
+
141
+ def test_prepared_statement_parameter_binding_with_index_key
142
+ r = @db.prepare('select x, y, z from t where z = ?').query(1 => 3)
143
+ assert_equal [{ x: 1, y: 2, z: 3 }], r
144
+
145
+ r = @db.prepare('select x, y, z from t where x = ?2').query(1 => 42, 2 => 4)
146
+ assert_equal [{ x: 4, y: 5, z: 6 }], r
147
+ end
148
+
149
+ def test_prepared_statement_value_casting
150
+ r = @db.prepare("select 'abc'").query_single_value
151
+ assert_equal 'abc', r
152
+
153
+ r = @db.prepare('select 123').query_single_value
154
+ assert_equal 123, r
155
+
156
+ r = @db.prepare('select 12.34').query_single_value
157
+ assert_equal 12.34, r
158
+
159
+ r = @db.prepare('select zeroblob(4)').query_single_value
160
+ assert_equal "\x00\x00\x00\x00", r
161
+
162
+ r = @db.prepare('select null').query_single_value
163
+ assert_nil r
164
+ end
165
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require 'sequel'
5
+
6
+ class SequelExtraliteTest < MiniTest::Test
7
+ def test_sequel
8
+ db = Sequel.connect('extralite::memory:')
9
+ db.create_table :items do
10
+ primary_key :id
11
+ String :name, unique: true, null: false
12
+ Float :price, null: false
13
+ end
14
+
15
+ items = db[:items]
16
+
17
+ items.insert(name: 'abc', price: 123)
18
+ items.insert(name: 'def', price: 456)
19
+ items.insert(name: 'ghi', price: 789)
20
+
21
+ assert_equal 3, items.count
22
+ assert_equal (123+456+789) / 3, items.avg(:price)
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: extralite-bundle
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.14'
5
+ platform: ruby
6
+ authors:
7
+ - Sharon Rosner
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.1.6
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.1.6
27
+ - !ruby/object:Gem::Dependency
28
+ name: minitest
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 5.15.0
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 5.15.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: simplecov
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '='
46
+ - !ruby/object:Gem::Version
47
+ version: 0.17.1
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '='
53
+ - !ruby/object:Gem::Version
54
+ version: 0.17.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.27
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.27
69
+ - !ruby/object:Gem::Dependency
70
+ name: sequel
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '='
74
+ - !ruby/object:Gem::Version
75
+ version: 5.51.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '='
81
+ - !ruby/object:Gem::Version
82
+ version: 5.51.0
83
+ description:
84
+ email: sharon@noteflakes.com
85
+ executables: []
86
+ extensions:
87
+ - ext/extralite/extconf-bundle.rb
88
+ extra_rdoc_files:
89
+ - README.md
90
+ files:
91
+ - ".github/FUNDING.yml"
92
+ - ".github/workflows/test.yml"
93
+ - ".gitignore"
94
+ - CHANGELOG.md
95
+ - Gemfile
96
+ - Gemfile.lock
97
+ - LICENSE
98
+ - README.md
99
+ - Rakefile
100
+ - TODO.md
101
+ - bin/update_sqlite_source
102
+ - ext/extralite/common.c
103
+ - ext/extralite/database.c
104
+ - ext/extralite/extconf-bundle.rb
105
+ - ext/extralite/extconf.rb
106
+ - ext/extralite/extralite.h
107
+ - ext/extralite/extralite_ext.c
108
+ - ext/extralite/extralite_sqlite3.c
109
+ - ext/extralite/prepared_statement.c
110
+ - ext/sqlite3/sqlite3.c
111
+ - ext/sqlite3/sqlite3.h
112
+ - extralite-bundle.gemspec
113
+ - extralite.gemspec
114
+ - gemspec.rb
115
+ - lib/extralite.rb
116
+ - lib/extralite/version.rb
117
+ - lib/sequel/adapters/extralite.rb
118
+ - test/extensions/text.dylib
119
+ - test/extensions/text.so
120
+ - test/helper.rb
121
+ - test/perf_ary.rb
122
+ - test/perf_hash.rb
123
+ - test/perf_prepared.rb
124
+ - test/run.rb
125
+ - test/test_database.rb
126
+ - test/test_extralite.rb
127
+ - test/test_prepared_statement.rb
128
+ - test/test_sequel.rb
129
+ homepage: https://github.com/digital-fabric/extralite
130
+ licenses:
131
+ - MIT
132
+ metadata:
133
+ source_code_uri: https://github.com/digital-fabric/extralite
134
+ documentation_uri: https://www.rubydoc.info/gems/extralite
135
+ homepage_uri: https://github.com/digital-fabric/extralite
136
+ changelog_uri: https://github.com/digital-fabric/extralite/blob/master/CHANGELOG.md
137
+ post_install_message:
138
+ rdoc_options:
139
+ - "--title"
140
+ - extralite
141
+ - "--main"
142
+ - README.md
143
+ require_paths:
144
+ - lib
145
+ required_ruby_version: !ruby/object:Gem::Requirement
146
+ requirements:
147
+ - - ">="
148
+ - !ruby/object:Gem::Version
149
+ version: '2.7'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ requirements:
152
+ - - ">="
153
+ - !ruby/object:Gem::Version
154
+ version: '0'
155
+ requirements: []
156
+ rubygems_version: 3.3.3
157
+ signing_key:
158
+ specification_version: 4
159
+ summary: Extra-lightweight SQLite3 wrapper for Ruby with bundled SQLite3
160
+ test_files: []