sqlite3 1.3.11-x64-mingw32 → 1.5.0.rc1-x64-mingw32

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 (54) hide show
  1. checksums.yaml +5 -5
  2. data/.gemtest +0 -0
  3. data/{API_CHANGES.rdoc → API_CHANGES.md} +3 -4
  4. data/CHANGELOG.md +419 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/Gemfile +2 -15
  7. data/LICENSE-DEPENDENCIES +20 -0
  8. data/README.md +233 -0
  9. data/ext/sqlite3/aggregator.c +273 -0
  10. data/ext/sqlite3/aggregator.h +12 -0
  11. data/ext/sqlite3/database.c +210 -182
  12. data/ext/sqlite3/database.h +2 -0
  13. data/ext/sqlite3/exception.c +6 -2
  14. data/ext/sqlite3/extconf.rb +148 -39
  15. data/ext/sqlite3/sqlite3.c +67 -1
  16. data/ext/sqlite3/sqlite3_ruby.h +0 -7
  17. data/ext/sqlite3/statement.c +15 -20
  18. data/faq/faq.md +431 -0
  19. data/faq/faq.yml +1 -1
  20. data/lib/sqlite3/2.6/sqlite3_native.so +0 -0
  21. data/lib/sqlite3/2.7/sqlite3_native.so +0 -0
  22. data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
  23. data/lib/sqlite3/constants.rb +2 -1
  24. data/lib/sqlite3/database.rb +209 -58
  25. data/lib/sqlite3/errors.rb +1 -10
  26. data/lib/sqlite3/pragmas.rb +372 -57
  27. data/lib/sqlite3/resultset.rb +2 -10
  28. data/lib/sqlite3/statement.rb +2 -1
  29. data/lib/sqlite3/translator.rb +1 -1
  30. data/lib/sqlite3/version.rb +4 -4
  31. data/lib/sqlite3.rb +5 -0
  32. data/test/helper.rb +9 -0
  33. data/test/test_database.rb +180 -9
  34. data/test/test_database_flags.rb +95 -0
  35. data/test/test_database_readonly.rb +9 -2
  36. data/test/test_database_readwrite.rb +41 -0
  37. data/test/test_integration.rb +12 -77
  38. data/test/test_integration_aggregate.rb +336 -0
  39. data/test/test_integration_resultset.rb +0 -17
  40. data/test/test_sqlite3.rb +16 -0
  41. data/test/test_statement.rb +12 -9
  42. metadata +55 -84
  43. data/CHANGELOG.rdoc +0 -287
  44. data/Manifest.txt +0 -52
  45. data/README.rdoc +0 -101
  46. data/Rakefile +0 -10
  47. data/lib/sqlite3/2.0/sqlite3_native.so +0 -0
  48. data/lib/sqlite3/2.1/sqlite3_native.so +0 -0
  49. data/lib/sqlite3/2.2/sqlite3_native.so +0 -0
  50. data/setup.rb +0 -1333
  51. data/tasks/faq.rake +0 -9
  52. data/tasks/gem.rake +0 -38
  53. data/tasks/native.rake +0 -52
  54. data/tasks/vendor_sqlite3.rake +0 -97
@@ -1,4 +1,6 @@
1
1
  require 'helper'
2
+ require 'tempfile'
3
+ require 'pathname'
2
4
 
3
5
  module SQLite3
4
6
  class TestDatabase < SQLite3::TestCase
@@ -6,10 +8,71 @@ module SQLite3
6
8
 
7
9
  def setup
8
10
  @db = SQLite3::Database.new(':memory:')
11
+ super
9
12
  end
10
13
 
11
14
  def test_segv
12
- assert_raises(TypeError) { SQLite3::Database.new 1 }
15
+ assert_raises { SQLite3::Database.new 1 }
16
+ end
17
+
18
+ def test_db_filename
19
+ tf = nil
20
+ assert_equal '', @db.filename('main')
21
+ tf = Tempfile.new 'thing'
22
+ @db = SQLite3::Database.new tf.path
23
+ assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('main'))
24
+ ensure
25
+ tf.unlink if tf
26
+ end
27
+
28
+ def test_filename
29
+ tf = nil
30
+ assert_equal '', @db.filename
31
+ tf = Tempfile.new 'thing'
32
+ @db = SQLite3::Database.new tf.path
33
+ assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename)
34
+ ensure
35
+ tf.unlink if tf
36
+ end
37
+
38
+ def test_filename_with_attachment
39
+ tf = nil
40
+ assert_equal '', @db.filename
41
+ tf = Tempfile.new 'thing'
42
+ @db.execute "ATTACH DATABASE '#{tf.path}' AS 'testing'"
43
+
44
+ assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('testing'))
45
+ ensure
46
+ tf.unlink if tf
47
+ end
48
+
49
+
50
+ def test_filename_to_path
51
+ tf = Tempfile.new 'thing'
52
+ pn = Pathname tf.path
53
+ db = SQLite3::Database.new pn
54
+ assert_equal pn.realdirpath.to_s, File.realdirpath(db.filename)
55
+ ensure
56
+ tf.close! if tf
57
+ end
58
+
59
+
60
+ def test_error_code
61
+ begin
62
+ db.execute 'SELECT'
63
+ rescue SQLite3::SQLException => e
64
+ end
65
+ assert_equal 1, e.code
66
+ end
67
+
68
+ def test_extended_error_code
69
+ db.extended_result_codes = true
70
+ db.execute 'CREATE TABLE "employees" ("token" integer NOT NULL)'
71
+ begin
72
+ db.execute 'INSERT INTO employees (token) VALUES (NULL)'
73
+ rescue SQLite3::ConstraintException => e
74
+ end
75
+ assert_equal 1299, e.code
13
76
  end
14
77
 
15
78
  def test_bignum
@@ -33,15 +96,17 @@ module SQLite3
33
96
 
34
97
  def test_get_first_row_with_type_translation_and_hash_results
35
98
  @db.results_as_hash = true
36
- assert_equal({0=>1, "1"=>1}, @db.get_first_row('SELECT 1'))
99
+ @db.type_translation = true
100
+ assert_equal({"1"=>1}, @db.get_first_row('SELECT 1'))
37
101
  end
38
102
 
39
103
  def test_execute_with_type_translation_and_hash
40
104
  @db.results_as_hash = true
105
+ @db.type_translation = true
41
106
  rows = []
42
107
  @db.execute('SELECT 1') { |row| rows << row }
43
108
 
44
- assert_equal({0=>1, "1"=>1}, rows.first)
109
+ assert_equal({"1"=>1}, rows.first)
45
110
  end
46
111
 
47
112
  def test_encoding
@@ -68,6 +133,59 @@ module SQLite3
68
133
  eosql
69
134
  end
70
135
 
136
+ def test_execute_batch2
137
+ @db.results_as_hash = true
138
+ return_value = @db.execute_batch2 <<-eosql
139
+ CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, name string);
140
+ INSERT INTO items (name) VALUES ("foo");
141
+ INSERT INTO items (name) VALUES ("bar");
142
+ SELECT * FROM items;
143
+ eosql
144
+ assert_equal return_value, [{"id"=>"1","name"=>"foo"}, {"id"=>"2", "name"=>"bar"}]
145
+
146
+ return_value = @db.execute_batch2('SELECT * FROM items;') do |result|
147
+ result["id"] = result["id"].to_i
148
+ result
149
+ end
150
+ assert_equal return_value, [{"id"=>1,"name"=>"foo"}, {"id"=>2, "name"=>"bar"}]
151
+
152
+ return_value = @db.execute_batch2('INSERT INTO items (name) VALUES ("oof")')
153
+ assert_equal return_value, []
154
+
155
+ return_value = @db.execute_batch2(
156
+ 'CREATE TABLE employees (id integer PRIMARY KEY AUTOINCREMENT, name string, age integer(3));
157
+ INSERT INTO employees (age) VALUES (30);
158
+ INSERT INTO employees (age) VALUES (40);
159
+ INSERT INTO employees (age) VALUES (20);
160
+ SELECT age FROM employees;') do |result|
161
+ result["age"] = result["age"].to_i
162
+ result
163
+ end
164
+ assert_equal return_value, [{"age"=>30}, {"age"=>40}, {"age"=>20}]
165
+
166
+ return_value = @db.execute_batch2('SELECT name FROM employees');
167
+ assert_equal return_value, [{"name"=>nil}, {"name"=>nil}, {"name"=>nil}]
168
+
169
+ @db.results_as_hash = false
170
+ return_value = @db.execute_batch2(
171
+ 'CREATE TABLE managers (id integer PRIMARY KEY AUTOINCREMENT, age integer(3));
172
+ INSERT INTO managers (age) VALUES (50);
173
+ INSERT INTO managers (age) VALUES (60);
174
+ SELECT id, age from managers;') do |result|
175
+ result = result.map do |res|
176
+ res.to_i
177
+ end
178
+ result
179
+ end
180
+ assert_equal return_value, [[1, 50], [2, 60]]
181
+
182
+ assert_raises (RuntimeError) do
183
+ # "names" is not a valid column
184
+ @db.execute_batch2 'INSERT INTO items (names) VALUES ("bazz")'
185
+ end
186
+
187
+ end
188
+
71
189
  def test_new
72
190
  db = SQLite3::Database.new(':memory:')
73
191
  assert db
@@ -109,6 +227,18 @@ module SQLite3
109
227
  assert thing.closed?
110
228
  end
111
229
 
230
+ def test_block_closes_self_even_raised
231
+ thing = nil
232
+ begin
233
+ SQLite3::Database.new(':memory:') do |db|
234
+ thing = db
235
+ raise
236
+ end
237
+ rescue
238
+ end
239
+ assert thing.closed?
240
+ end
241
+
112
242
  def test_prepare
113
243
  db = SQLite3::Database.new(':memory:')
114
244
  stmt = db.prepare('select "hello world"')
@@ -136,7 +266,7 @@ module SQLite3
136
266
  db.execute("create table foo ( a integer primary key, b text )")
137
267
  db.execute("insert into foo (b) values ('hello')")
138
268
  rows = db.execute("select * from foo")
139
- assert_equal [{0=>1, "a"=>1, "b"=>"hello", 1=>"hello"}], rows
269
+ assert_equal [{"a"=>1, "b"=>"hello"}], rows
140
270
  end
141
271
 
142
272
  def test_execute_yields_hash
@@ -144,7 +274,7 @@ module SQLite3
144
274
  db.execute("create table foo ( a integer primary key, b text )")
145
275
  db.execute("insert into foo (b) values ('hello')")
146
276
  db.execute("select * from foo") do |row|
147
- assert_equal({0=>1, "a"=>1, "b"=>"hello", 1=>"hello"}, row)
277
+ assert_equal({"a"=>1, "b"=>"hello"}, row)
148
278
  end
149
279
  end
150
280
 
@@ -231,7 +361,10 @@ module SQLite3
231
361
  nil
232
362
  end
233
363
  @db.execute("select hello(2.2, 'foo', NULL)")
234
- assert_equal [2.2, 'foo', nil], called_with
364
+
365
+ assert_in_delta(2.2, called_with[0], 0.0001)
366
+ assert_equal("foo", called_with[1])
367
+ assert_nil(called_with[2])
235
368
  end
236
369
 
237
370
  def test_define_varargs
@@ -241,7 +374,10 @@ module SQLite3
241
374
  nil
242
375
  end
243
376
  @db.execute("select hello(2.2, 'foo', NULL)")
244
- assert_equal [2.2, 'foo', nil], called_with
377
+
378
+ assert_in_delta(2.2, called_with[0], 0.0001)
379
+ assert_equal("foo", called_with[1])
380
+ assert_nil(called_with[2])
245
381
  end
246
382
 
247
383
  def test_call_func_blob
@@ -261,12 +397,30 @@ module SQLite3
261
397
  end
262
398
 
263
399
  def test_function_return_types
264
- [10, 2.2, nil, "foo"].each do |thing|
400
+ [10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing|
265
401
  @db.define_function("hello") { |a| thing }
266
402
  assert_equal [thing], @db.execute("select hello('world')").first
267
403
  end
268
404
  end
269
405
 
406
+ def test_function_gc_segfault
407
+ @db.create_function("bug", -1) { |func, *values| func.result = values.join }
408
+ # With a lot of data and a lot of threads, try to induce a GC segfault.
409
+ params = Array.new(127, "?" * 28000)
410
+ proc = Proc.new {
411
+ db.execute("select bug(#{Array.new(params.length, "?").join(",")})", params)
412
+ }
413
+ m = Mutex.new
414
+ 30.times.map { Thread.new { m.synchronize { proc.call } } }.each(&:join)
415
+ end
416
+
417
+ def test_function_return_type_round_trip
418
+ [10, 2.2, nil, "foo", Blob.new("foo\0bar")].each do |thing|
419
+ @db.define_function("hello") { |a| a }
420
+ assert_equal [thing], @db.execute("select hello(hello(?))", [thing]).first
421
+ end
422
+ end
423
+
270
424
  def test_define_function_closed
271
425
  @db.close
272
426
  assert_raise(SQLite3::Exception) do
@@ -321,7 +475,7 @@ module SQLite3
321
475
  def call action, a, b, c, d; nil end
322
476
  }.new
323
477
  stmt = @db.prepare("select 'fooooo'")
324
- assert_equal nil, stmt.step
478
+ assert_nil stmt.step
325
479
  end
326
480
 
327
481
  def test_authorizer_fail
@@ -363,5 +517,22 @@ module SQLite3
363
517
  def test_execute_with_named_bind_params
364
518
  assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
365
519
  end
520
+
521
+ def test_strict_mode
522
+ unless Gem::Requirement.new(">= 3.29.0").satisfied_by?(Gem::Version.new(SQLite3::SQLITE_VERSION))
523
+ skip("strict mode feature not available in #{SQLite3::SQLITE_VERSION}")
524
+ end
525
+
526
+ db = SQLite3::Database.new(':memory:')
527
+ db.execute('create table numbers (val int);')
528
+ db.execute('create index index_numbers_nope ON numbers ("nope");') # nothing raised
529
+
530
+ db = SQLite3::Database.new(':memory:', :strict => true)
531
+ db.execute('create table numbers (val int);')
532
+ error = assert_raises SQLite3::SQLException do
533
+ db.execute('create index index_numbers_nope ON numbers ("nope");')
534
+ end
535
+ assert_includes error.message, "no such column: nope"
536
+ end
366
537
  end
367
538
  end
@@ -0,0 +1,95 @@
1
+ require 'helper'
2
+
3
+ module SQLite3
4
+ class TestDatabaseFlags < SQLite3::TestCase
5
+ def setup
6
+ File.unlink 'test-flags.db' if File.exist?('test-flags.db')
7
+ @db = SQLite3::Database.new('test-flags.db')
8
+ @db.execute("CREATE TABLE foos (id integer)")
9
+ @db.close
10
+ end
11
+
12
+ def teardown
13
+ @db.close unless @db.closed?
14
+ File.unlink 'test-flags.db' if File.exist?('test-flags.db')
15
+ end
16
+
17
+ def test_open_database_flags_constants
18
+ defined_to_date = [:READONLY, :READWRITE, :CREATE, :DELETEONCLOSE,
19
+ :EXCLUSIVE, :MAIN_DB, :TEMP_DB, :TRANSIENT_DB,
20
+ :MAIN_JOURNAL, :TEMP_JOURNAL, :SUBJOURNAL,
21
+ :MASTER_JOURNAL, :NOMUTEX, :FULLMUTEX]
22
+ if SQLite3::SQLITE_VERSION_NUMBER > 3007002
23
+ defined_to_date += [:AUTOPROXY, :SHAREDCACHE, :PRIVATECACHE, :WAL]
24
+ end
25
+ if SQLite3::SQLITE_VERSION_NUMBER > 3007007
26
+ defined_to_date += [:URI]
27
+ end
28
+ if SQLite3::SQLITE_VERSION_NUMBER > 3007013
29
+ defined_to_date += [:MEMORY]
30
+ end
31
+ assert defined_to_date.sort == SQLite3::Constants::Open.constants.sort
32
+ end
33
+
34
+ def test_open_database_flags_conflicts_with_readonly
35
+ assert_raise(RuntimeError) do
36
+ @db = SQLite3::Database.new('test-flags.db', :flags => 2, :readonly => true)
37
+ end
38
+ end
39
+
40
+ def test_open_database_flags_conflicts_with_readwrite
41
+ assert_raise(RuntimeError) do
42
+ @db = SQLite3::Database.new('test-flags.db', :flags => 2, :readwrite => true)
43
+ end
44
+ end
45
+
46
+ def test_open_database_readonly_flags
47
+ @db = SQLite3::Database.new('test-flags.db', :flags => SQLite3::Constants::Open::READONLY)
48
+ assert @db.readonly?
49
+ end
50
+
51
+ def test_open_database_readwrite_flags
52
+ @db = SQLite3::Database.new('test-flags.db', :flags => SQLite3::Constants::Open::READWRITE)
53
+ assert !@db.readonly?
54
+ end
55
+
56
+ def test_open_database_readonly_flags_cant_open
57
+ File.unlink 'test-flags.db'
58
+ assert_raise(SQLite3::CantOpenException) do
59
+ @db = SQLite3::Database.new('test-flags.db', :flags => SQLite3::Constants::Open::READONLY)
60
+ end
61
+ end
62
+
63
+ def test_open_database_readwrite_flags_cant_open
64
+ File.unlink 'test-flags.db'
65
+ assert_raise(SQLite3::CantOpenException) do
66
+ @db = SQLite3::Database.new('test-flags.db', :flags => SQLite3::Constants::Open::READWRITE)
67
+ end
68
+ end
69
+
70
+ def test_open_database_misuse_flags
71
+ assert_raise(SQLite3::MisuseException) do
72
+ flags = SQLite3::Constants::Open::READONLY | SQLite3::Constants::Open::READWRITE # <== incompatible flags
73
+ @db = SQLite3::Database.new('test-flags.db', :flags => flags)
74
+ end
75
+ end
76
+
77
+ def test_open_database_create_flags
78
+ File.unlink 'test-flags.db'
79
+ flags = SQLite3::Constants::Open::READWRITE | SQLite3::Constants::Open::CREATE
80
+ @db = SQLite3::Database.new('test-flags.db', :flags => flags) do |db|
81
+ db.execute("CREATE TABLE foos (id integer)")
82
+ db.execute("INSERT INTO foos (id) VALUES (12)")
83
+ end
84
+ assert File.exist?('test-flags.db')
85
+ end
86
+
87
+ def test_open_database_exotic_flags
88
+ flags = SQLite3::Constants::Open::READWRITE | SQLite3::Constants::Open::CREATE
89
+ exotic_flags = SQLite3::Constants::Open::NOMUTEX | SQLite3::Constants::Open::TEMP_DB
90
+ @db = SQLite3::Database.new('test-flags.db', :flags => flags | exotic_flags)
91
+ @db.execute("INSERT INTO foos (id) VALUES (12)")
92
+ assert @db.changes == 1
93
+ end
94
+ end
95
+ end
@@ -3,7 +3,7 @@ require 'helper'
3
3
  module SQLite3
4
4
  class TestDatabaseReadonly < SQLite3::TestCase
5
5
  def setup
6
- File.unlink 'test-readonly.db' if File.exists?('test-readonly.db')
6
+ File.unlink 'test-readonly.db' if File.exist?('test-readonly.db')
7
7
  @db = SQLite3::Database.new('test-readonly.db')
8
8
  @db.execute("CREATE TABLE foos (id integer)")
9
9
  @db.close
@@ -11,7 +11,7 @@ module SQLite3
11
11
 
12
12
  def teardown
13
13
  @db.close unless @db.closed?
14
- File.unlink 'test-readonly.db'
14
+ File.unlink 'test-readonly.db' if File.exist?('test-readonly.db')
15
15
  end
16
16
 
17
17
  def test_open_readonly_database
@@ -19,6 +19,13 @@ module SQLite3
19
19
  assert @db.readonly?
20
20
  end
21
21
 
22
+ def test_open_readonly_not_exists_database
23
+ File.unlink 'test-readonly.db'
24
+ assert_raise(SQLite3::CantOpenException) do
25
+ @db = SQLite3::Database.new('test-readonly.db', :readonly => true)
26
+ end
27
+ end
28
+
22
29
  def test_insert_readonly_database
23
30
  @db = SQLite3::Database.new('test-readonly.db', :readonly => true)
24
31
  assert_raise(SQLite3::ReadOnlyException) do
@@ -0,0 +1,41 @@
1
+ require 'helper'
2
+
3
+ module SQLite3
4
+ class TestDatabaseReadwrite < SQLite3::TestCase
5
+ def setup
6
+ File.unlink 'test-readwrite.db' if File.exist?('test-readwrite.db')
7
+ @db = SQLite3::Database.new('test-readwrite.db')
8
+ @db.execute("CREATE TABLE foos (id integer)")
9
+ @db.close
10
+ end
11
+
12
+ def teardown
13
+ @db.close unless @db.closed?
14
+ File.unlink 'test-readwrite.db' if File.exist?('test-readwrite.db')
15
+ end
16
+
17
+ def test_open_readwrite_database
18
+ @db = SQLite3::Database.new('test-readwrite.db', :readwrite => true)
19
+ assert !@db.readonly?
20
+ end
21
+
22
+ def test_open_readwrite_readonly_database
23
+ assert_raise(RuntimeError) do
24
+ @db = SQLite3::Database.new('test-readwrite.db', :readwrite => true, :readonly => true)
25
+ end
26
+ end
27
+
28
+ def test_open_readwrite_not_exists_database
29
+ File.unlink 'test-readwrite.db'
30
+ assert_raise(SQLite3::CantOpenException) do
31
+ @db = SQLite3::Database.new('test-readwrite.db', :readonly => true)
32
+ end
33
+ end
34
+
35
+ def test_insert_readwrite_database
36
+ @db = SQLite3::Database.new('test-readwrite.db', :readwrite => true)
37
+ @db.execute("INSERT INTO foos (id) VALUES (12)")
38
+ assert @db.changes == 1
39
+ end
40
+ end
41
+ end
@@ -359,21 +359,33 @@ class TC_Database_Integration < SQLite3::TestCase
359
359
  def test_get_first_value_no_bind_no_match
360
360
  result = @db.get_first_value( "select b, a from foo where a=100" )
361
361
  assert_nil result
362
+ @db.results_as_hash = true
363
+ result = @db.get_first_value( "select b, a from foo where a=100" )
364
+ assert_nil result
362
365
  end
363
366
 
364
367
  def test_get_first_value_no_bind_with_match
365
368
  result = @db.get_first_value( "select b, a from foo where a=1" )
366
369
  assert_equal "foo", result
370
+ @db.results_as_hash = true
371
+ result = @db.get_first_value( "select b, a from foo where a=1" )
372
+ assert_equal "foo", result
367
373
  end
368
374
 
369
375
  def test_get_first_value_with_bind_no_match
370
376
  result = @db.get_first_value( "select b, a from foo where a=?", 100 )
371
377
  assert_nil result
378
+ @db.results_as_hash = true
379
+ result = @db.get_first_value( "select b, a from foo where a=?", 100 )
380
+ assert_nil result
372
381
  end
373
382
 
374
383
  def test_get_first_value_with_bind_with_match
375
384
  result = @db.get_first_value( "select b, a from foo where a=?", 1 )
376
385
  assert_equal "foo", result
386
+ @db.results_as_hash = true
387
+ result = @db.get_first_value( "select b, a from foo where a=?", 1 )
388
+ assert_equal "foo", result
377
389
  end
378
390
 
379
391
  def test_last_insert_row_id
@@ -487,83 +499,6 @@ class TC_Database_Integration < SQLite3::TestCase
487
499
  assert_match( />>>.*<<</, value )
488
500
  end
489
501
 
490
- def test_create_aggregate_without_block
491
- step = proc do |ctx,a|
492
- ctx[:sum] ||= 0
493
- ctx[:sum] += a.to_i
494
- end
495
-
496
- final = proc { |ctx| ctx.result = ctx[:sum] }
497
-
498
- @db.create_aggregate( "accumulate", 1, step, final )
499
-
500
- value = @db.get_first_value( "select accumulate(a) from foo" )
501
- assert_equal 6, value
502
- end
503
-
504
- def test_create_aggregate_with_block
505
- @db.create_aggregate( "accumulate", 1 ) do
506
- step do |ctx,a|
507
- ctx[:sum] ||= 0
508
- ctx[:sum] += a.to_i
509
- end
510
-
511
- finalize { |ctx| ctx.result = ctx[:sum] }
512
- end
513
-
514
- value = @db.get_first_value( "select accumulate(a) from foo" )
515
- assert_equal 6, value
516
- end
517
-
518
- def test_create_aggregate_with_no_data
519
- @db.create_aggregate( "accumulate", 1 ) do
520
- step do |ctx,a|
521
- ctx[:sum] ||= 0
522
- ctx[:sum] += a.to_i
523
- end
524
-
525
- finalize { |ctx| ctx.result = ctx[:sum] || 0 }
526
- end
527
-
528
- value = @db.get_first_value(
529
- "select accumulate(a) from foo where a = 100" )
530
- assert_equal 0, value
531
- end
532
-
533
- class AggregateHandler
534
- class << self
535
- def arity; 1; end
536
- def text_rep; SQLite3::Constants::TextRep::ANY; end
537
- def name; "multiply"; end
538
- end
539
- def step(ctx, a)
540
- ctx[:buffer] ||= 1
541
- ctx[:buffer] *= a.to_i
542
- end
543
- def finalize(ctx); ctx.result = ctx[:buffer]; end
544
- end
545
-
546
- def test_aggregate_initialized_twice
547
- initialized = 0
548
- handler = Class.new(AggregateHandler) do
549
- define_method(:initialize) do
550
- initialized += 1
551
- super()
552
- end
553
- end
554
-
555
- @db.create_aggregate_handler handler
556
- @db.get_first_value( "select multiply(a) from foo" )
557
- @db.get_first_value( "select multiply(a) from foo" )
558
- assert_equal 2, initialized
559
- end
560
-
561
- def test_create_aggregate_handler
562
- @db.create_aggregate_handler AggregateHandler
563
- value = @db.get_first_value( "select multiply(a) from foo" )
564
- assert_equal 6, value
565
- end
566
-
567
502
  def test_bind_array_parameter
568
503
  result = @db.get_first_value( "select b from foo where a=? and b=?",
569
504
  [ 1, "foo" ] )