sqlite3 1.4.2 → 1.7.2

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.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/{API_CHANGES.rdoc → API_CHANGES.md} +3 -4
  3. data/CHANGELOG.md +641 -0
  4. data/CONTRIBUTING.md +34 -0
  5. data/FAQ.md +431 -0
  6. data/Gemfile +7 -14
  7. data/INSTALLATION.md +259 -0
  8. data/LICENSE-DEPENDENCIES +20 -0
  9. data/README.md +110 -0
  10. data/dependencies.yml +14 -0
  11. data/ext/sqlite3/aggregator.c +10 -10
  12. data/ext/sqlite3/backup.c +26 -13
  13. data/ext/sqlite3/database.c +89 -38
  14. data/ext/sqlite3/database.h +2 -0
  15. data/ext/sqlite3/extconf.rb +269 -84
  16. data/ext/sqlite3/sqlite3.c +5 -2
  17. data/ext/sqlite3/sqlite3_ruby.h +5 -2
  18. data/ext/sqlite3/statement.c +37 -28
  19. data/lib/sqlite3/constants.rb +1 -1
  20. data/lib/sqlite3/database.rb +55 -30
  21. data/lib/sqlite3/pragmas.rb +13 -6
  22. data/lib/sqlite3/resultset.rb +4 -12
  23. data/lib/sqlite3/statement.rb +2 -1
  24. data/lib/sqlite3/translator.rb +2 -3
  25. data/lib/sqlite3/version.rb +3 -5
  26. data/ports/archives/sqlite-autoconf-3450100.tar.gz +0 -0
  27. data/test/helper.rb +9 -0
  28. data/test/test_database.rb +182 -17
  29. data/test/test_deprecated.rb +10 -5
  30. data/test/test_encoding.rb +10 -0
  31. data/test/test_integration_resultset.rb +2 -2
  32. data/test/test_integration_statement.rb +2 -2
  33. data/test/test_pragmas.rb +22 -0
  34. data/test/test_result_set.rb +18 -8
  35. data/test/test_sqlite3.rb +9 -0
  36. data/test/test_statement.rb +28 -1
  37. data/test/test_statement_execute.rb +4 -0
  38. metadata +36 -144
  39. data/.travis.yml +0 -33
  40. data/CHANGELOG.rdoc +0 -318
  41. data/Manifest.txt +0 -60
  42. data/README.rdoc +0 -118
  43. data/Rakefile +0 -8
  44. data/appveyor.yml +0 -36
  45. data/faq/faq.rb +0 -145
  46. data/faq/faq.yml +0 -426
  47. data/rakelib/faq.rake +0 -9
  48. data/rakelib/gem.rake +0 -40
  49. data/rakelib/native.rake +0 -56
  50. data/rakelib/vendor_sqlite3.rake +0 -97
  51. data/setup.rb +0 -1333
@@ -11,6 +11,10 @@ module SQLite3
11
11
  super
12
12
  end
13
13
 
14
+ def teardown
15
+ @db.close unless @db.closed?
16
+ end
17
+
14
18
  def test_segv
15
19
  assert_raises { SQLite3::Database.new 1 }
16
20
  end
@@ -20,7 +24,7 @@ module SQLite3
20
24
  assert_equal '', @db.filename('main')
21
25
  tf = Tempfile.new 'thing'
22
26
  @db = SQLite3::Database.new tf.path
23
- assert_equal File.expand_path(tf.path), File.expand_path(@db.filename('main'))
27
+ assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('main'))
24
28
  ensure
25
29
  tf.unlink if tf
26
30
  end
@@ -30,7 +34,7 @@ module SQLite3
30
34
  assert_equal '', @db.filename
31
35
  tf = Tempfile.new 'thing'
32
36
  @db = SQLite3::Database.new tf.path
33
- assert_equal File.expand_path(tf.path), File.expand_path(@db.filename)
37
+ assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename)
34
38
  ensure
35
39
  tf.unlink if tf
36
40
  end
@@ -40,11 +44,24 @@ module SQLite3
40
44
  assert_equal '', @db.filename
41
45
  tf = Tempfile.new 'thing'
42
46
  @db.execute "ATTACH DATABASE '#{tf.path}' AS 'testing'"
43
- assert_equal File.expand_path(tf.path), File.expand_path(@db.filename('testing'))
47
+
48
+ assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('testing'))
44
49
  ensure
45
50
  tf.unlink if tf
46
51
  end
47
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
+
48
65
  def test_error_code
49
66
  begin
50
67
  db.execute 'SELECT'
@@ -84,15 +101,20 @@ module SQLite3
84
101
 
85
102
  def test_get_first_row_with_type_translation_and_hash_results
86
103
  @db.results_as_hash = true
87
- @db.type_translation = true
88
- assert_equal({"1"=>1}, @db.get_first_row('SELECT 1'))
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
89
108
  end
90
109
 
91
110
  def test_execute_with_type_translation_and_hash
92
- @db.results_as_hash = true
93
- @db.type_translation = true
94
111
  rows = []
95
- @db.execute('SELECT 1') { |row| rows << row }
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
96
118
 
97
119
  assert_equal({"1"=>1}, rows.first)
98
120
  end
@@ -176,7 +198,23 @@ module SQLite3
176
198
 
177
199
  def test_new
178
200
  db = SQLite3::Database.new(':memory:')
179
- assert db
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
180
218
  end
181
219
 
182
220
  def test_new_yields_self
@@ -187,6 +225,14 @@ module SQLite3
187
225
  assert_instance_of(SQLite3::Database, thing)
188
226
  end
189
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
+
190
236
  def test_new_with_options
191
237
  # determine if Ruby is running on Big Endian platform
192
238
  utf16 = ([1].pack("I") == [1].pack("N")) ? "UTF-16BE" : "UTF-16LE"
@@ -197,7 +243,9 @@ module SQLite3
197
243
  db = SQLite3::Database.new(Iconv.conv(utf16, 'UTF-8', ':memory:'),
198
244
  :utf16 => true)
199
245
  end
200
- assert db
246
+ assert_instance_of(SQLite3::Database, db)
247
+ ensure
248
+ db.close if db
201
249
  end
202
250
 
203
251
  def test_close
@@ -215,6 +263,15 @@ module SQLite3
215
263
  assert thing.closed?
216
264
  end
217
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
+
218
275
  def test_block_closes_self_even_raised
219
276
  thing = nil
220
277
  begin
@@ -227,10 +284,24 @@ module SQLite3
227
284
  assert thing.closed?
228
285
  end
229
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
+
230
299
  def test_prepare
231
300
  db = SQLite3::Database.new(':memory:')
232
301
  stmt = db.prepare('select "hello world"')
233
302
  assert_instance_of(SQLite3::Statement, stmt)
303
+ ensure
304
+ stmt.close if stmt
234
305
  end
235
306
 
236
307
  def test_block_prepare_does_not_double_close
@@ -349,7 +420,10 @@ module SQLite3
349
420
  nil
350
421
  end
351
422
  @db.execute("select hello(2.2, 'foo', NULL)")
352
- assert_equal [2.2, 'foo', nil], called_with
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])
353
427
  end
354
428
 
355
429
  def test_define_varargs
@@ -359,7 +433,10 @@ module SQLite3
359
433
  nil
360
434
  end
361
435
  @db.execute("select hello(2.2, 'foo', NULL)")
362
- assert_equal [2.2, 'foo', nil], called_with
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])
363
440
  end
364
441
 
365
442
  def test_call_func_blob
@@ -441,15 +518,19 @@ module SQLite3
441
518
  end
442
519
 
443
520
  def test_authorizer_ok
521
+ statements = []
522
+
444
523
  @db.authorizer = Class.new {
445
524
  def call action, a, b, c, d; true end
446
525
  }.new
447
- @db.prepare("select 'fooooo'")
526
+ statements << @db.prepare("select 'fooooo'")
448
527
 
449
528
  @db.authorizer = Class.new {
450
529
  def call action, a, b, c, d; 0 end
451
530
  }.new
452
- @db.prepare("select 'fooooo'")
531
+ statements << @db.prepare("select 'fooooo'")
532
+ ensure
533
+ statements.each(&:close)
453
534
  end
454
535
 
455
536
  def test_authorizer_ignore
@@ -458,6 +539,8 @@ module SQLite3
458
539
  }.new
459
540
  stmt = @db.prepare("select 'fooooo'")
460
541
  assert_nil stmt.step
542
+ ensure
543
+ stmt.close if stmt
461
544
  end
462
545
 
463
546
  def test_authorizer_fail
@@ -478,14 +561,18 @@ module SQLite3
478
561
  end
479
562
 
480
563
  @db.authorizer = nil
481
- @db.prepare("select 'fooooo'")
564
+ s = @db.prepare("select 'fooooo'")
565
+ ensure
566
+ s.close if s
482
567
  end
483
568
 
484
569
  def test_close_with_open_statements
485
- @db.prepare("select 'foo'")
570
+ s = @db.prepare("select 'foo'")
486
571
  assert_raises(SQLite3::BusyException) do
487
572
  @db.close
488
573
  end
574
+ ensure
575
+ s.close if s
489
576
  end
490
577
 
491
578
  def test_execute_with_empty_bind_params
@@ -493,11 +580,89 @@ module SQLite3
493
580
  end
494
581
 
495
582
  def test_query_with_named_bind_params
496
- assert_equal [['foo']], @db.query("select :n", {'n' => 'foo'}).to_a
583
+ resultset = @db.query("select :n", {'n' => 'foo'})
584
+ assert_equal [['foo']], resultset.to_a
585
+ ensure
586
+ resultset.close if resultset
497
587
  end
498
588
 
499
589
  def test_execute_with_named_bind_params
500
590
  assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
501
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
502
667
  end
503
668
  end
@@ -2,8 +2,6 @@ require 'helper'
2
2
 
3
3
  module SQLite3
4
4
  class TestDeprecated < SQLite3::TestCase
5
- attr_reader :db
6
-
7
5
  def setup
8
6
  super
9
7
  @warn_before = $-w
@@ -15,10 +13,13 @@ module SQLite3
15
13
  def teardown
16
14
  super
17
15
  $-w = @warn_before
16
+ @db.close
18
17
  end
19
18
 
20
19
  def test_query_with_many_bind_params_not_nil
21
- assert_equal [[1, 2]], db.query('select ?, ?', 1, 2).to_a
20
+ rs = @db.query('select ?, ?', 1, 2)
21
+ assert_equal [[1, 2]], rs.to_a
22
+ rs.close
22
23
  end
23
24
 
24
25
  def test_execute_with_many_bind_params_not_nil
@@ -26,11 +27,15 @@ module SQLite3
26
27
  end
27
28
 
28
29
  def test_query_with_many_bind_params
29
- assert_equal [[nil, 1]], @db.query("select ?, ?", nil, 1).to_a
30
+ rs = @db.query("select ?, ?", nil, 1)
31
+ assert_equal [[nil, 1]], rs.to_a
32
+ rs.close
30
33
  end
31
34
 
32
35
  def test_query_with_nil_bind_params
33
- assert_equal [['foo']], @db.query("select 'foo'", nil).to_a
36
+ rs = @db.query("select 'foo'", nil)
37
+ assert_equal [['foo']], rs.to_a
38
+ rs.close
34
39
  end
35
40
 
36
41
  def test_execute_with_many_bind_params
@@ -11,6 +11,10 @@ module SQLite3
11
11
  @db.execute(@create);
12
12
  end
13
13
 
14
+ def teardown
15
+ @db.close
16
+ end
17
+
14
18
  def test_select_encoding_on_utf_16
15
19
  str = "foo"
16
20
  utf16 = ([1].pack("I") == [1].pack("N")) ? "UTF-16BE" : "UTF-16LE"
@@ -24,6 +28,7 @@ module SQLite3
24
28
  assert_equal 1, stmt.to_a.length
25
29
  stmt.reset!
26
30
  end
31
+ stmt.close
27
32
  end
28
33
 
29
34
  def test_insert_encoding
@@ -39,6 +44,7 @@ module SQLite3
39
44
  stmt.to_a
40
45
  stmt.reset!
41
46
  end
47
+ stmt.close
42
48
 
43
49
  db.execute('select data from ex').flatten.each do |s|
44
50
  assert_equal str, s
@@ -55,6 +61,7 @@ module SQLite3
55
61
  stmt = @db.prepare('insert into ex(data) values (?)')
56
62
  stmt.bind_param 1, str
57
63
  stmt.step
64
+ stmt.close
58
65
 
59
66
  Encoding.default_internal = 'EUC-JP'
60
67
  string = @db.execute('select data from ex').first.first
@@ -73,6 +80,7 @@ module SQLite3
73
80
  stmt = @db.prepare('insert into foo(data) values (?)')
74
81
  stmt.bind_param(1, SQLite3::Blob.new(str))
75
82
  stmt.step
83
+ stmt.close
76
84
 
77
85
  string = @db.execute('select data from foo').first.first
78
86
  assert_equal Encoding.find('ASCII-8BIT'), string.encoding
@@ -85,6 +93,7 @@ module SQLite3
85
93
  stmt = @db.prepare('insert into foo(data) values (?)')
86
94
  stmt.bind_param(1, str.dup.force_encoding("ASCII-8BIT"))
87
95
  stmt.step
96
+ stmt.close
88
97
 
89
98
  string = @db.execute('select data from foo').first.first
90
99
  assert_equal Encoding.find('ASCII-8BIT'), string.encoding
@@ -97,6 +106,7 @@ module SQLite3
97
106
  stmt = @db.prepare('insert into foo(data) values (?)')
98
107
  stmt.bind_param(1, SQLite3::Blob.new(str))
99
108
  stmt.step
109
+ stmt.close
100
110
 
101
111
  string = @db.execute('select data from foo').first.first
102
112
  assert_equal Encoding.find('ASCII-8BIT'), string.encoding
@@ -101,8 +101,8 @@ class TC_ResultSet < SQLite3::TestCase
101
101
  hash = @result.next
102
102
  assert_equal( { "a" => 1, "b" => "foo" },
103
103
  hash )
104
- assert_equal hash[0], 1
105
- assert_equal hash[1], "foo"
104
+ assert_equal hash[@result.columns[0]], 1
105
+ assert_equal hash[@result.columns[1]], "foo"
106
106
  end
107
107
 
108
108
  def test_each
@@ -77,10 +77,10 @@ class TC_Statement < SQLite3::TestCase
77
77
  def test_bind_param_with_various_types
78
78
  @db.transaction do
79
79
  @db.execute "create table all_types ( a integer primary key, b float, c string, d integer )"
80
- @db.execute "insert into all_types ( b, c, d ) values ( 1.4, 'hello', 68719476735 )"
80
+ @db.execute "insert into all_types ( b, c, d ) values ( 1.5, 'hello', 68719476735 )"
81
81
  end
82
82
 
83
- assert_equal 1, @db.execute( "select * from all_types where b = ?", 1.4 ).length
83
+ assert_equal 1, @db.execute( "select * from all_types where b = ?", 1.5 ).length
84
84
  assert_equal 1, @db.execute( "select * from all_types where c = ?", 'hello').length
85
85
  assert_equal 1, @db.execute( "select * from all_types where d = ?", 68719476735).length
86
86
  end
@@ -0,0 +1,22 @@
1
+ require 'helper'
2
+
3
+ module SQLite3
4
+ class TestPragmas < SQLite3::TestCase
5
+ def setup
6
+ super
7
+ @db = SQLite3::Database.new(":memory:")
8
+ end
9
+
10
+ def test_get_boolean_pragma
11
+ refute(@db.get_boolean_pragma("read_uncommitted"))
12
+ end
13
+
14
+ def test_set_boolean_pragma
15
+ @db.set_boolean_pragma("read_uncommitted", 1)
16
+
17
+ assert(@db.get_boolean_pragma("read_uncommitted"))
18
+ ensure
19
+ @db.set_boolean_pragma("read_uncommitted", 0)
20
+ end
21
+ end
22
+ end
@@ -2,29 +2,38 @@ require 'helper'
2
2
 
3
3
  module SQLite3
4
4
  class TestResultSet < SQLite3::TestCase
5
+ def setup
6
+ @db = SQLite3::Database.new ':memory:'
7
+ super
8
+ end
9
+
10
+ def teardown
11
+ super
12
+ @db.close
13
+ end
14
+
5
15
  def test_each_hash
6
- db = SQLite3::Database.new ':memory:'
7
- db.execute "create table foo ( a integer primary key, b text )"
16
+ @db.execute "create table foo ( a integer primary key, b text )"
8
17
  list = ('a'..'z').to_a
9
18
  list.each do |t|
10
- db.execute "insert into foo (b) values (\"#{t}\")"
19
+ @db.execute "insert into foo (b) values (\"#{t}\")"
11
20
  end
12
21
 
13
- rs = db.prepare('select * from foo').execute
22
+ rs = @db.prepare('select * from foo').execute
14
23
  rs.each_hash do |hash|
15
24
  assert_equal list[hash['a'] - 1], hash['b']
16
25
  end
26
+ rs.close
17
27
  end
18
28
 
19
29
  def test_next_hash
20
- db = SQLite3::Database.new ':memory:'
21
- db.execute "create table foo ( a integer primary key, b text )"
30
+ @db.execute "create table foo ( a integer primary key, b text )"
22
31
  list = ('a'..'z').to_a
23
32
  list.each do |t|
24
- db.execute "insert into foo (b) values (\"#{t}\")"
33
+ @db.execute "insert into foo (b) values (\"#{t}\")"
25
34
  end
26
35
 
27
- rs = db.prepare('select * from foo').execute
36
+ rs = @db.prepare('select * from foo').execute
28
37
  rows = []
29
38
  while row = rs.next_hash
30
39
  rows << row
@@ -32,6 +41,7 @@ module SQLite3
32
41
  rows.each do |hash|
33
42
  assert_equal list[hash['a'] - 1], hash['b']
34
43
  end
44
+ rs.close
35
45
  end
36
46
  end
37
47
  end
data/test/test_sqlite3.rb CHANGED
@@ -17,5 +17,14 @@ module SQLite3
17
17
  refute SQLite3.threadsafe?
18
18
  end
19
19
  end
20
+
21
+ def test_version_strings
22
+ skip if SQLite3::VERSION.include?("test") # see set-version-to-timestamp rake task
23
+ assert_equal(SQLite3::VERSION, SQLite3::VersionProxy::STRING)
24
+ end
25
+
26
+ def test_compiled_version_and_loaded_version
27
+ assert_equal(SQLite3::SQLITE_VERSION, SQLite3::SQLITE_LOADED_VERSION)
28
+ end
20
29
  end
21
30
  end