extralite-bundle 1.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []