sqlite3 1.7.3 → 2.5.0
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 +4 -4
- data/CHANGELOG.md +292 -0
- data/CONTRIBUTING.md +33 -7
- data/FAQ.md +43 -77
- data/INSTALLATION.md +14 -6
- data/LICENSE +18 -22
- data/README.md +97 -9
- data/dependencies.yml +10 -11
- data/ext/sqlite3/aggregator.c +142 -145
- data/ext/sqlite3/aggregator.h +2 -4
- data/ext/sqlite3/backup.c +74 -65
- data/ext/sqlite3/backup.h +2 -2
- data/ext/sqlite3/database.c +621 -493
- data/ext/sqlite3/database.h +13 -4
- data/ext/sqlite3/exception.c +116 -92
- data/ext/sqlite3/exception.h +5 -1
- data/ext/sqlite3/extconf.rb +33 -24
- data/ext/sqlite3/sqlite3.c +176 -115
- data/ext/sqlite3/sqlite3_ruby.h +2 -2
- data/ext/sqlite3/statement.c +553 -300
- data/ext/sqlite3/statement.h +4 -3
- data/ext/sqlite3/timespec.h +20 -0
- data/lib/sqlite3/constants.rb +195 -47
- data/lib/sqlite3/database.rb +223 -187
- data/lib/sqlite3/errors.rb +54 -1
- data/lib/sqlite3/fork_safety.rb +66 -0
- data/lib/sqlite3/pragmas.rb +140 -136
- data/lib/sqlite3/resultset.rb +14 -97
- data/lib/sqlite3/statement.rb +58 -13
- data/lib/sqlite3/value.rb +17 -20
- data/lib/sqlite3/version.rb +2 -21
- data/lib/sqlite3/version_info.rb +17 -0
- data/lib/sqlite3.rb +8 -4
- data/ports/archives/sqlite-autoconf-3470200.tar.gz +0 -0
- metadata +9 -37
- data/API_CHANGES.md +0 -49
- data/ChangeLog.cvs +0 -88
- data/Gemfile +0 -10
- data/LICENSE-DEPENDENCIES +0 -20
- data/lib/sqlite3/translator.rb +0 -117
- data/ports/archives/sqlite-autoconf-3450200.tar.gz +0 -0
- data/test/helper.rb +0 -27
- data/test/test_backup.rb +0 -33
- data/test/test_collation.rb +0 -82
- data/test/test_database.rb +0 -668
- data/test/test_database_flags.rb +0 -95
- data/test/test_database_readonly.rb +0 -36
- data/test/test_database_readwrite.rb +0 -41
- data/test/test_deprecated.rb +0 -49
- data/test/test_encoding.rb +0 -165
- data/test/test_integration.rb +0 -507
- data/test/test_integration_aggregate.rb +0 -336
- data/test/test_integration_open_close.rb +0 -30
- data/test/test_integration_pending.rb +0 -115
- data/test/test_integration_resultset.rb +0 -142
- data/test/test_integration_statement.rb +0 -194
- data/test/test_pragmas.rb +0 -22
- data/test/test_result_set.rb +0 -47
- data/test/test_sqlite3.rb +0 -30
- data/test/test_statement.rb +0 -290
- data/test/test_statement_execute.rb +0 -39
data/test/test_database.rb
DELETED
@@ -1,668 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
require 'tempfile'
|
3
|
-
require 'pathname'
|
4
|
-
|
5
|
-
module SQLite3
|
6
|
-
class TestDatabase < SQLite3::TestCase
|
7
|
-
attr_reader :db
|
8
|
-
|
9
|
-
def setup
|
10
|
-
@db = SQLite3::Database.new(':memory:')
|
11
|
-
super
|
12
|
-
end
|
13
|
-
|
14
|
-
def teardown
|
15
|
-
@db.close unless @db.closed?
|
16
|
-
end
|
17
|
-
|
18
|
-
def test_segv
|
19
|
-
assert_raises { SQLite3::Database.new 1 }
|
20
|
-
end
|
21
|
-
|
22
|
-
def test_db_filename
|
23
|
-
tf = nil
|
24
|
-
assert_equal '', @db.filename('main')
|
25
|
-
tf = Tempfile.new 'thing'
|
26
|
-
@db = SQLite3::Database.new tf.path
|
27
|
-
assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('main'))
|
28
|
-
ensure
|
29
|
-
tf.unlink if tf
|
30
|
-
end
|
31
|
-
|
32
|
-
def test_filename
|
33
|
-
tf = nil
|
34
|
-
assert_equal '', @db.filename
|
35
|
-
tf = Tempfile.new 'thing'
|
36
|
-
@db = SQLite3::Database.new tf.path
|
37
|
-
assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename)
|
38
|
-
ensure
|
39
|
-
tf.unlink if tf
|
40
|
-
end
|
41
|
-
|
42
|
-
def test_filename_with_attachment
|
43
|
-
tf = nil
|
44
|
-
assert_equal '', @db.filename
|
45
|
-
tf = Tempfile.new 'thing'
|
46
|
-
@db.execute "ATTACH DATABASE '#{tf.path}' AS 'testing'"
|
47
|
-
|
48
|
-
assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('testing'))
|
49
|
-
ensure
|
50
|
-
tf.unlink if tf
|
51
|
-
end
|
52
|
-
|
53
|
-
|
54
|
-
def test_filename_to_path
|
55
|
-
tf = Tempfile.new 'thing'
|
56
|
-
pn = Pathname tf.path
|
57
|
-
db = SQLite3::Database.new pn
|
58
|
-
assert_equal pn.realdirpath.to_s, File.realdirpath(db.filename)
|
59
|
-
ensure
|
60
|
-
tf.close! if tf
|
61
|
-
db.close if db
|
62
|
-
end
|
63
|
-
|
64
|
-
|
65
|
-
def test_error_code
|
66
|
-
begin
|
67
|
-
db.execute 'SELECT'
|
68
|
-
rescue SQLite3::SQLException => e
|
69
|
-
end
|
70
|
-
assert_equal 1, e.code
|
71
|
-
end
|
72
|
-
|
73
|
-
def test_extended_error_code
|
74
|
-
db.extended_result_codes = true
|
75
|
-
db.execute 'CREATE TABLE "employees" ("token" integer NOT NULL)'
|
76
|
-
begin
|
77
|
-
db.execute 'INSERT INTO employees (token) VALUES (NULL)'
|
78
|
-
rescue SQLite3::ConstraintException => e
|
79
|
-
end
|
80
|
-
assert_equal 1299, e.code
|
81
|
-
end
|
82
|
-
|
83
|
-
def test_bignum
|
84
|
-
num = 4907021672125087844
|
85
|
-
db.execute 'CREATE TABLE "employees" ("token" integer(8), "name" varchar(20) NOT NULL)'
|
86
|
-
db.execute "INSERT INTO employees(name, token) VALUES('employee-1', ?)", [num]
|
87
|
-
rows = db.execute 'select token from employees'
|
88
|
-
assert_equal num, rows.first.first
|
89
|
-
end
|
90
|
-
|
91
|
-
def test_blob
|
92
|
-
@db.execute("CREATE TABLE blobs ( id INTEGER, hash BLOB(10) )")
|
93
|
-
blob = Blob.new("foo\0bar")
|
94
|
-
@db.execute("INSERT INTO blobs VALUES (0, ?)", [blob])
|
95
|
-
assert_equal [[0, blob, blob.length, blob.length*2]], @db.execute("SELECT id, hash, length(hash), length(hex(hash)) FROM blobs")
|
96
|
-
end
|
97
|
-
|
98
|
-
def test_get_first_row
|
99
|
-
assert_equal [1], @db.get_first_row('SELECT 1')
|
100
|
-
end
|
101
|
-
|
102
|
-
def test_get_first_row_with_type_translation_and_hash_results
|
103
|
-
@db.results_as_hash = true
|
104
|
-
capture_io do # hush translation deprecation warnings
|
105
|
-
@db.type_translation = true
|
106
|
-
assert_equal({"1"=>1}, @db.get_first_row('SELECT 1'))
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_execute_with_type_translation_and_hash
|
111
|
-
rows = []
|
112
|
-
@db.results_as_hash = true
|
113
|
-
|
114
|
-
capture_io do # hush translation deprecation warnings
|
115
|
-
@db.type_translation = true
|
116
|
-
@db.execute('SELECT 1') { |row| rows << row }
|
117
|
-
end
|
118
|
-
|
119
|
-
assert_equal({"1"=>1}, rows.first)
|
120
|
-
end
|
121
|
-
|
122
|
-
def test_encoding
|
123
|
-
assert @db.encoding, 'database has encoding'
|
124
|
-
end
|
125
|
-
|
126
|
-
def test_changes
|
127
|
-
@db.execute("CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, number integer)")
|
128
|
-
assert_equal 0, @db.changes
|
129
|
-
@db.execute("INSERT INTO items (number) VALUES (10)")
|
130
|
-
assert_equal 1, @db.changes
|
131
|
-
@db.execute_batch(
|
132
|
-
"UPDATE items SET number = (number + :nn) WHERE (number = :n)",
|
133
|
-
{"nn" => 20, "n" => 10})
|
134
|
-
assert_equal 1, @db.changes
|
135
|
-
assert_equal [[30]], @db.execute("select number from items")
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_batch_last_comment_is_processed
|
139
|
-
# FIXME: nil as a successful return value is kinda dumb
|
140
|
-
assert_nil @db.execute_batch <<-eosql
|
141
|
-
CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT);
|
142
|
-
-- omg
|
143
|
-
eosql
|
144
|
-
end
|
145
|
-
|
146
|
-
def test_execute_batch2
|
147
|
-
@db.results_as_hash = true
|
148
|
-
return_value = @db.execute_batch2 <<-eosql
|
149
|
-
CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, name string);
|
150
|
-
INSERT INTO items (name) VALUES ("foo");
|
151
|
-
INSERT INTO items (name) VALUES ("bar");
|
152
|
-
SELECT * FROM items;
|
153
|
-
eosql
|
154
|
-
assert_equal return_value, [{"id"=>"1","name"=>"foo"}, {"id"=>"2", "name"=>"bar"}]
|
155
|
-
|
156
|
-
return_value = @db.execute_batch2('SELECT * FROM items;') do |result|
|
157
|
-
result["id"] = result["id"].to_i
|
158
|
-
result
|
159
|
-
end
|
160
|
-
assert_equal return_value, [{"id"=>1,"name"=>"foo"}, {"id"=>2, "name"=>"bar"}]
|
161
|
-
|
162
|
-
return_value = @db.execute_batch2('INSERT INTO items (name) VALUES ("oof")')
|
163
|
-
assert_equal return_value, []
|
164
|
-
|
165
|
-
return_value = @db.execute_batch2(
|
166
|
-
'CREATE TABLE employees (id integer PRIMARY KEY AUTOINCREMENT, name string, age integer(3));
|
167
|
-
INSERT INTO employees (age) VALUES (30);
|
168
|
-
INSERT INTO employees (age) VALUES (40);
|
169
|
-
INSERT INTO employees (age) VALUES (20);
|
170
|
-
SELECT age FROM employees;') do |result|
|
171
|
-
result["age"] = result["age"].to_i
|
172
|
-
result
|
173
|
-
end
|
174
|
-
assert_equal return_value, [{"age"=>30}, {"age"=>40}, {"age"=>20}]
|
175
|
-
|
176
|
-
return_value = @db.execute_batch2('SELECT name FROM employees');
|
177
|
-
assert_equal return_value, [{"name"=>nil}, {"name"=>nil}, {"name"=>nil}]
|
178
|
-
|
179
|
-
@db.results_as_hash = false
|
180
|
-
return_value = @db.execute_batch2(
|
181
|
-
'CREATE TABLE managers (id integer PRIMARY KEY AUTOINCREMENT, age integer(3));
|
182
|
-
INSERT INTO managers (age) VALUES (50);
|
183
|
-
INSERT INTO managers (age) VALUES (60);
|
184
|
-
SELECT id, age from managers;') do |result|
|
185
|
-
result = result.map do |res|
|
186
|
-
res.to_i
|
187
|
-
end
|
188
|
-
result
|
189
|
-
end
|
190
|
-
assert_equal return_value, [[1, 50], [2, 60]]
|
191
|
-
|
192
|
-
assert_raises (RuntimeError) do
|
193
|
-
# "names" is not a valid column
|
194
|
-
@db.execute_batch2 'INSERT INTO items (names) VALUES ("bazz")'
|
195
|
-
end
|
196
|
-
|
197
|
-
end
|
198
|
-
|
199
|
-
def test_new
|
200
|
-
db = SQLite3::Database.new(':memory:')
|
201
|
-
assert_instance_of(SQLite3::Database, db)
|
202
|
-
ensure
|
203
|
-
db.close if db
|
204
|
-
end
|
205
|
-
|
206
|
-
def test_open
|
207
|
-
db = SQLite3::Database.open(':memory:')
|
208
|
-
assert_instance_of(SQLite3::Database, db)
|
209
|
-
ensure
|
210
|
-
db.close if db
|
211
|
-
end
|
212
|
-
|
213
|
-
def test_open_returns_block_result
|
214
|
-
result = SQLite3::Database.open(':memory:') do |db|
|
215
|
-
:foo
|
216
|
-
end
|
217
|
-
assert_equal :foo, result
|
218
|
-
end
|
219
|
-
|
220
|
-
def test_new_yields_self
|
221
|
-
thing = nil
|
222
|
-
SQLite3::Database.new(':memory:') do |db|
|
223
|
-
thing = db
|
224
|
-
end
|
225
|
-
assert_instance_of(SQLite3::Database, thing)
|
226
|
-
end
|
227
|
-
|
228
|
-
def test_open_yields_self
|
229
|
-
thing = nil
|
230
|
-
SQLite3::Database.open(':memory:') do |db|
|
231
|
-
thing = db
|
232
|
-
end
|
233
|
-
assert_instance_of(SQLite3::Database, thing)
|
234
|
-
end
|
235
|
-
|
236
|
-
def test_new_with_options
|
237
|
-
# determine if Ruby is running on Big Endian platform
|
238
|
-
utf16 = ([1].pack("I") == [1].pack("N")) ? "UTF-16BE" : "UTF-16LE"
|
239
|
-
|
240
|
-
if RUBY_VERSION >= "1.9"
|
241
|
-
db = SQLite3::Database.new(':memory:'.encode(utf16), :utf16 => true)
|
242
|
-
else
|
243
|
-
db = SQLite3::Database.new(Iconv.conv(utf16, 'UTF-8', ':memory:'),
|
244
|
-
:utf16 => true)
|
245
|
-
end
|
246
|
-
assert_instance_of(SQLite3::Database, db)
|
247
|
-
ensure
|
248
|
-
db.close if db
|
249
|
-
end
|
250
|
-
|
251
|
-
def test_close
|
252
|
-
db = SQLite3::Database.new(':memory:')
|
253
|
-
db.close
|
254
|
-
assert db.closed?
|
255
|
-
end
|
256
|
-
|
257
|
-
def test_block_closes_self
|
258
|
-
thing = nil
|
259
|
-
SQLite3::Database.new(':memory:') do |db|
|
260
|
-
thing = db
|
261
|
-
assert !thing.closed?
|
262
|
-
end
|
263
|
-
assert thing.closed?
|
264
|
-
end
|
265
|
-
|
266
|
-
def test_open_with_block_closes_self
|
267
|
-
thing = nil
|
268
|
-
SQLite3::Database.open(':memory:') do |db|
|
269
|
-
thing = db
|
270
|
-
assert !thing.closed?
|
271
|
-
end
|
272
|
-
assert thing.closed?
|
273
|
-
end
|
274
|
-
|
275
|
-
def test_block_closes_self_even_raised
|
276
|
-
thing = nil
|
277
|
-
begin
|
278
|
-
SQLite3::Database.new(':memory:') do |db|
|
279
|
-
thing = db
|
280
|
-
raise
|
281
|
-
end
|
282
|
-
rescue
|
283
|
-
end
|
284
|
-
assert thing.closed?
|
285
|
-
end
|
286
|
-
|
287
|
-
def test_open_with_block_closes_self_even_raised
|
288
|
-
thing = nil
|
289
|
-
begin
|
290
|
-
SQLite3::Database.open(':memory:') do |db|
|
291
|
-
thing = db
|
292
|
-
raise
|
293
|
-
end
|
294
|
-
rescue
|
295
|
-
end
|
296
|
-
assert thing.closed?
|
297
|
-
end
|
298
|
-
|
299
|
-
def test_prepare
|
300
|
-
db = SQLite3::Database.new(':memory:')
|
301
|
-
stmt = db.prepare('select "hello world"')
|
302
|
-
assert_instance_of(SQLite3::Statement, stmt)
|
303
|
-
ensure
|
304
|
-
stmt.close if stmt
|
305
|
-
end
|
306
|
-
|
307
|
-
def test_block_prepare_does_not_double_close
|
308
|
-
db = SQLite3::Database.new(':memory:')
|
309
|
-
r = db.prepare('select "hello world"') do |stmt|
|
310
|
-
stmt.close
|
311
|
-
:foo
|
312
|
-
end
|
313
|
-
assert_equal :foo, r
|
314
|
-
end
|
315
|
-
|
316
|
-
def test_total_changes
|
317
|
-
db = SQLite3::Database.new(':memory:')
|
318
|
-
db.execute("create table foo ( a integer primary key, b text )")
|
319
|
-
db.execute("insert into foo (b) values ('hello')")
|
320
|
-
assert_equal 1, db.total_changes
|
321
|
-
end
|
322
|
-
|
323
|
-
def test_execute_returns_list_of_hash
|
324
|
-
db = SQLite3::Database.new(':memory:', :results_as_hash => true)
|
325
|
-
db.execute("create table foo ( a integer primary key, b text )")
|
326
|
-
db.execute("insert into foo (b) values ('hello')")
|
327
|
-
rows = db.execute("select * from foo")
|
328
|
-
assert_equal [{"a"=>1, "b"=>"hello"}], rows
|
329
|
-
end
|
330
|
-
|
331
|
-
def test_execute_yields_hash
|
332
|
-
db = SQLite3::Database.new(':memory:', :results_as_hash => true)
|
333
|
-
db.execute("create table foo ( a integer primary key, b text )")
|
334
|
-
db.execute("insert into foo (b) values ('hello')")
|
335
|
-
db.execute("select * from foo") do |row|
|
336
|
-
assert_equal({"a"=>1, "b"=>"hello"}, row)
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
def test_table_info
|
341
|
-
db = SQLite3::Database.new(':memory:', :results_as_hash => true)
|
342
|
-
db.execute("create table foo ( a integer primary key, b text )")
|
343
|
-
info = [{
|
344
|
-
"name" => "a",
|
345
|
-
"pk" => 1,
|
346
|
-
"notnull" => 0,
|
347
|
-
"type" => "integer",
|
348
|
-
"dflt_value" => nil,
|
349
|
-
"cid" => 0
|
350
|
-
},
|
351
|
-
{
|
352
|
-
"name" => "b",
|
353
|
-
"pk" => 0,
|
354
|
-
"notnull" => 0,
|
355
|
-
"type" => "text",
|
356
|
-
"dflt_value" => nil,
|
357
|
-
"cid" => 1
|
358
|
-
}]
|
359
|
-
assert_equal info, db.table_info('foo')
|
360
|
-
end
|
361
|
-
|
362
|
-
def test_total_changes_closed
|
363
|
-
db = SQLite3::Database.new(':memory:')
|
364
|
-
db.close
|
365
|
-
assert_raise(SQLite3::Exception) do
|
366
|
-
db.total_changes
|
367
|
-
end
|
368
|
-
end
|
369
|
-
|
370
|
-
def test_trace_requires_opendb
|
371
|
-
@db.close
|
372
|
-
assert_raise(SQLite3::Exception) do
|
373
|
-
@db.trace { |x| }
|
374
|
-
end
|
375
|
-
end
|
376
|
-
|
377
|
-
def test_trace_with_block
|
378
|
-
result = nil
|
379
|
-
@db.trace { |sql| result = sql }
|
380
|
-
@db.execute "select 'foo'"
|
381
|
-
assert_equal "select 'foo'", result
|
382
|
-
end
|
383
|
-
|
384
|
-
def test_trace_with_object
|
385
|
-
obj = Class.new {
|
386
|
-
attr_accessor :result
|
387
|
-
def call sql; @result = sql end
|
388
|
-
}.new
|
389
|
-
|
390
|
-
@db.trace(obj)
|
391
|
-
@db.execute "select 'foo'"
|
392
|
-
assert_equal "select 'foo'", obj.result
|
393
|
-
end
|
394
|
-
|
395
|
-
def test_trace_takes_nil
|
396
|
-
@db.trace(nil)
|
397
|
-
@db.execute "select 'foo'"
|
398
|
-
end
|
399
|
-
|
400
|
-
def test_last_insert_row_id_closed
|
401
|
-
@db.close
|
402
|
-
assert_raise(SQLite3::Exception) do
|
403
|
-
@db.last_insert_row_id
|
404
|
-
end
|
405
|
-
end
|
406
|
-
|
407
|
-
def test_define_function
|
408
|
-
called_with = nil
|
409
|
-
@db.define_function("hello") do |value|
|
410
|
-
called_with = value
|
411
|
-
end
|
412
|
-
@db.execute("select hello(10)")
|
413
|
-
assert_equal 10, called_with
|
414
|
-
end
|
415
|
-
|
416
|
-
def test_call_func_arg_type
|
417
|
-
called_with = nil
|
418
|
-
@db.define_function("hello") do |b, c, d|
|
419
|
-
called_with = [b, c, d]
|
420
|
-
nil
|
421
|
-
end
|
422
|
-
@db.execute("select hello(2.2, 'foo', NULL)")
|
423
|
-
|
424
|
-
assert_in_delta(2.2, called_with[0], 0.0001)
|
425
|
-
assert_equal("foo", called_with[1])
|
426
|
-
assert_nil(called_with[2])
|
427
|
-
end
|
428
|
-
|
429
|
-
def test_define_varargs
|
430
|
-
called_with = nil
|
431
|
-
@db.define_function("hello") do |*args|
|
432
|
-
called_with = args
|
433
|
-
nil
|
434
|
-
end
|
435
|
-
@db.execute("select hello(2.2, 'foo', NULL)")
|
436
|
-
|
437
|
-
assert_in_delta(2.2, called_with[0], 0.0001)
|
438
|
-
assert_equal("foo", called_with[1])
|
439
|
-
assert_nil(called_with[2])
|
440
|
-
end
|
441
|
-
|
442
|
-
def test_call_func_blob
|
443
|
-
called_with = nil
|
444
|
-
@db.define_function("hello") do |a, b|
|
445
|
-
called_with = [a, b, a.length]
|
446
|
-
nil
|
447
|
-
end
|
448
|
-
blob = Blob.new("a\0fine\0kettle\0of\0fish")
|
449
|
-
@db.execute("select hello(?, length(?))", [blob, blob])
|
450
|
-
assert_equal [blob, blob.length, 21], called_with
|
451
|
-
end
|
452
|
-
|
453
|
-
def test_function_return
|
454
|
-
@db.define_function("hello") { |a| 10 }
|
455
|
-
assert_equal [10], @db.execute("select hello('world')").first
|
456
|
-
end
|
457
|
-
|
458
|
-
def test_function_return_types
|
459
|
-
[10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing|
|
460
|
-
@db.define_function("hello") { |a| thing }
|
461
|
-
assert_equal [thing], @db.execute("select hello('world')").first
|
462
|
-
end
|
463
|
-
end
|
464
|
-
|
465
|
-
def test_function_gc_segfault
|
466
|
-
@db.create_function("bug", -1) { |func, *values| func.result = values.join }
|
467
|
-
# With a lot of data and a lot of threads, try to induce a GC segfault.
|
468
|
-
params = Array.new(127, "?" * 28000)
|
469
|
-
proc = Proc.new {
|
470
|
-
db.execute("select bug(#{Array.new(params.length, "?").join(",")})", params)
|
471
|
-
}
|
472
|
-
m = Mutex.new
|
473
|
-
30.times.map { Thread.new { m.synchronize { proc.call } } }.each(&:join)
|
474
|
-
end
|
475
|
-
|
476
|
-
def test_function_return_type_round_trip
|
477
|
-
[10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing|
|
478
|
-
@db.define_function("hello") { |a| a }
|
479
|
-
assert_equal [thing], @db.execute("select hello(hello(?))", [thing]).first
|
480
|
-
end
|
481
|
-
end
|
482
|
-
|
483
|
-
def test_define_function_closed
|
484
|
-
@db.close
|
485
|
-
assert_raise(SQLite3::Exception) do
|
486
|
-
@db.define_function('foo') { }
|
487
|
-
end
|
488
|
-
end
|
489
|
-
|
490
|
-
def test_inerrupt_closed
|
491
|
-
@db.close
|
492
|
-
assert_raise(SQLite3::Exception) do
|
493
|
-
@db.interrupt
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
def test_define_aggregate
|
498
|
-
@db.execute "create table foo ( a integer primary key, b text )"
|
499
|
-
@db.execute "insert into foo ( b ) values ( 'foo' )"
|
500
|
-
@db.execute "insert into foo ( b ) values ( 'bar' )"
|
501
|
-
@db.execute "insert into foo ( b ) values ( 'baz' )"
|
502
|
-
|
503
|
-
acc = Class.new {
|
504
|
-
attr_reader :sum
|
505
|
-
alias :finalize :sum
|
506
|
-
def initialize
|
507
|
-
@sum = 0
|
508
|
-
end
|
509
|
-
|
510
|
-
def step a
|
511
|
-
@sum += a
|
512
|
-
end
|
513
|
-
}.new
|
514
|
-
|
515
|
-
@db.define_aggregator("accumulate", acc)
|
516
|
-
value = @db.get_first_value( "select accumulate(a) from foo" )
|
517
|
-
assert_equal 6, value
|
518
|
-
end
|
519
|
-
|
520
|
-
def test_authorizer_ok
|
521
|
-
statements = []
|
522
|
-
|
523
|
-
@db.authorizer = Class.new {
|
524
|
-
def call action, a, b, c, d; true end
|
525
|
-
}.new
|
526
|
-
statements << @db.prepare("select 'fooooo'")
|
527
|
-
|
528
|
-
@db.authorizer = Class.new {
|
529
|
-
def call action, a, b, c, d; 0 end
|
530
|
-
}.new
|
531
|
-
statements << @db.prepare("select 'fooooo'")
|
532
|
-
ensure
|
533
|
-
statements.each(&:close)
|
534
|
-
end
|
535
|
-
|
536
|
-
def test_authorizer_ignore
|
537
|
-
@db.authorizer = Class.new {
|
538
|
-
def call action, a, b, c, d; nil end
|
539
|
-
}.new
|
540
|
-
stmt = @db.prepare("select 'fooooo'")
|
541
|
-
assert_nil stmt.step
|
542
|
-
ensure
|
543
|
-
stmt.close if stmt
|
544
|
-
end
|
545
|
-
|
546
|
-
def test_authorizer_fail
|
547
|
-
@db.authorizer = Class.new {
|
548
|
-
def call action, a, b, c, d; false end
|
549
|
-
}.new
|
550
|
-
assert_raises(SQLite3::AuthorizationException) do
|
551
|
-
@db.prepare("select 'fooooo'")
|
552
|
-
end
|
553
|
-
end
|
554
|
-
|
555
|
-
def test_remove_auth
|
556
|
-
@db.authorizer = Class.new {
|
557
|
-
def call action, a, b, c, d; false end
|
558
|
-
}.new
|
559
|
-
assert_raises(SQLite3::AuthorizationException) do
|
560
|
-
@db.prepare("select 'fooooo'")
|
561
|
-
end
|
562
|
-
|
563
|
-
@db.authorizer = nil
|
564
|
-
s = @db.prepare("select 'fooooo'")
|
565
|
-
ensure
|
566
|
-
s.close if s
|
567
|
-
end
|
568
|
-
|
569
|
-
def test_close_with_open_statements
|
570
|
-
s = @db.prepare("select 'foo'")
|
571
|
-
assert_raises(SQLite3::BusyException) do
|
572
|
-
@db.close
|
573
|
-
end
|
574
|
-
ensure
|
575
|
-
s.close if s
|
576
|
-
end
|
577
|
-
|
578
|
-
def test_execute_with_empty_bind_params
|
579
|
-
assert_equal [['foo']], @db.execute("select 'foo'", [])
|
580
|
-
end
|
581
|
-
|
582
|
-
def test_query_with_named_bind_params
|
583
|
-
resultset = @db.query("select :n", {'n' => 'foo'})
|
584
|
-
assert_equal [['foo']], resultset.to_a
|
585
|
-
ensure
|
586
|
-
resultset.close if resultset
|
587
|
-
end
|
588
|
-
|
589
|
-
def test_execute_with_named_bind_params
|
590
|
-
assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
|
591
|
-
end
|
592
|
-
|
593
|
-
def test_strict_mode
|
594
|
-
unless Gem::Requirement.new(">= 3.29.0").satisfied_by?(Gem::Version.new(SQLite3::SQLITE_VERSION))
|
595
|
-
skip("strict mode feature not available in #{SQLite3::SQLITE_VERSION}")
|
596
|
-
end
|
597
|
-
|
598
|
-
db = SQLite3::Database.new(':memory:')
|
599
|
-
db.execute('create table numbers (val int);')
|
600
|
-
db.execute('create index index_numbers_nope ON numbers ("nope");') # nothing raised
|
601
|
-
|
602
|
-
db = SQLite3::Database.new(':memory:', :strict => true)
|
603
|
-
db.execute('create table numbers (val int);')
|
604
|
-
error = assert_raises SQLite3::SQLException do
|
605
|
-
db.execute('create index index_numbers_nope ON numbers ("nope");')
|
606
|
-
end
|
607
|
-
assert_includes error.message, "no such column: nope"
|
608
|
-
end
|
609
|
-
|
610
|
-
def test_load_extension_with_nonstring_argument
|
611
|
-
db = SQLite3::Database.new(':memory:')
|
612
|
-
skip("extensions are not enabled") unless db.respond_to?(:load_extension)
|
613
|
-
assert_raises(TypeError) { db.load_extension(1) }
|
614
|
-
assert_raises(TypeError) { db.load_extension(Pathname.new("foo.so")) }
|
615
|
-
end
|
616
|
-
|
617
|
-
def test_raw_float_infinity
|
618
|
-
# https://github.com/sparklemotion/sqlite3-ruby/issues/396
|
619
|
-
skip if SQLite3::SQLITE_LOADED_VERSION >= "3.43.0"
|
620
|
-
|
621
|
-
db = SQLite3::Database.new ":memory:"
|
622
|
-
db.execute("create table foo (temperature float)")
|
623
|
-
db.execute("insert into foo values (?)", 37.5)
|
624
|
-
db.execute("insert into foo values (?)", Float::INFINITY)
|
625
|
-
assert_equal Float::INFINITY, db.execute("select avg(temperature) from foo").first.first
|
626
|
-
end
|
627
|
-
|
628
|
-
def test_default_transaction_mode
|
629
|
-
tf = Tempfile.new 'database_default_transaction_mode'
|
630
|
-
SQLite3::Database.new(tf.path) do |db|
|
631
|
-
db.execute("create table foo (score int)")
|
632
|
-
db.execute("insert into foo values (?)", 1)
|
633
|
-
end
|
634
|
-
|
635
|
-
test_cases = [
|
636
|
-
{mode: nil, read: true, write: true},
|
637
|
-
{mode: :deferred, read: true, write: true},
|
638
|
-
{mode: :immediate, read: true, write: false},
|
639
|
-
{mode: :exclusive, read: false, write: false},
|
640
|
-
]
|
641
|
-
|
642
|
-
test_cases.each do |item|
|
643
|
-
db = SQLite3::Database.new tf.path, default_transaction_mode: item[:mode]
|
644
|
-
db2 = SQLite3::Database.new tf.path
|
645
|
-
db.transaction do
|
646
|
-
sql_for_read_test = "select * from foo"
|
647
|
-
if item[:read]
|
648
|
-
assert_nothing_raised{ db2.execute(sql_for_read_test) }
|
649
|
-
else
|
650
|
-
assert_raises(SQLite3::BusyException){ db2.execute(sql_for_read_test) }
|
651
|
-
end
|
652
|
-
|
653
|
-
sql_for_write_test = "insert into foo values (2)"
|
654
|
-
if item[:write]
|
655
|
-
assert_nothing_raised{ db2.execute(sql_for_write_test) }
|
656
|
-
else
|
657
|
-
assert_raises(SQLite3::BusyException){ db2.execute(sql_for_write_test) }
|
658
|
-
end
|
659
|
-
end
|
660
|
-
ensure
|
661
|
-
db.close if db && !db.closed?
|
662
|
-
db2.close if db2 && !db2.closed?
|
663
|
-
end
|
664
|
-
ensure
|
665
|
-
tf.unlink if tf
|
666
|
-
end
|
667
|
-
end
|
668
|
-
end
|