sqlite3 1.3.13-x64-mingw32 → 1.5.0-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sqlite3 might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/.gemtest +0 -0
- data/{API_CHANGES.rdoc → API_CHANGES.md} +3 -4
- data/CHANGELOG.md +425 -0
- data/CONTRIBUTING.md +24 -0
- data/Gemfile +2 -14
- data/LICENSE-DEPENDENCIES +20 -0
- data/README.md +233 -0
- data/ext/sqlite3/aggregator.c +274 -0
- data/ext/sqlite3/aggregator.h +12 -0
- data/ext/sqlite3/database.c +171 -206
- data/ext/sqlite3/database.h +2 -0
- data/ext/sqlite3/exception.c +6 -2
- data/ext/sqlite3/extconf.rb +236 -55
- data/ext/sqlite3/sqlite3.c +12 -1
- data/ext/sqlite3/sqlite3_ruby.h +3 -7
- data/ext/sqlite3/statement.c +15 -20
- data/faq/faq.md +431 -0
- data/faq/faq.yml +1 -1
- data/lib/sqlite3/2.6/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.7/sqlite3_native.so +0 -0
- data/lib/sqlite3/3.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/constants.rb +2 -1
- data/lib/sqlite3/database.rb +202 -52
- data/lib/sqlite3/errors.rb +1 -10
- data/lib/sqlite3/pragmas.rb +17 -10
- data/lib/sqlite3/resultset.rb +2 -10
- data/lib/sqlite3/statement.rb +2 -1
- data/lib/sqlite3/translator.rb +1 -1
- data/lib/sqlite3/version.rb +3 -5
- data/test/helper.rb +9 -0
- data/test/test_database.rb +126 -11
- data/test/test_database_flags.rb +95 -0
- data/test/test_database_readwrite.rb +41 -0
- data/test/test_integration.rb +12 -81
- data/test/test_integration_aggregate.rb +336 -0
- data/test/test_integration_resultset.rb +0 -17
- data/test/test_sqlite3.rb +9 -0
- data/test/test_statement.rb +11 -8
- metadata +54 -85
- data/CHANGELOG.rdoc +0 -292
- data/Manifest.txt +0 -52
- data/README.rdoc +0 -118
- data/Rakefile +0 -10
- data/lib/sqlite3/2.0/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.1/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.2/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.3/sqlite3_native.so +0 -0
- data/lib/sqlite3/2.4/sqlite3_native.so +0 -0
- data/setup.rb +0 -1333
- data/tasks/faq.rake +0 -9
- data/tasks/gem.rake +0 -38
- data/tasks/native.rake +0 -52
- data/tasks/vendor_sqlite3.rake +0 -97
data/test/test_database.rb
CHANGED
@@ -12,7 +12,7 @@ module SQLite3
|
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_segv
|
15
|
-
assert_raises
|
15
|
+
assert_raises { SQLite3::Database.new 1 }
|
16
16
|
end
|
17
17
|
|
18
18
|
def test_db_filename
|
@@ -20,7 +20,7 @@ module SQLite3
|
|
20
20
|
assert_equal '', @db.filename('main')
|
21
21
|
tf = Tempfile.new 'thing'
|
22
22
|
@db = SQLite3::Database.new tf.path
|
23
|
-
assert_equal File.
|
23
|
+
assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('main'))
|
24
24
|
ensure
|
25
25
|
tf.unlink if tf
|
26
26
|
end
|
@@ -30,7 +30,7 @@ module SQLite3
|
|
30
30
|
assert_equal '', @db.filename
|
31
31
|
tf = Tempfile.new 'thing'
|
32
32
|
@db = SQLite3::Database.new tf.path
|
33
|
-
assert_equal File.
|
33
|
+
assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename)
|
34
34
|
ensure
|
35
35
|
tf.unlink if tf
|
36
36
|
end
|
@@ -40,11 +40,41 @@ module SQLite3
|
|
40
40
|
assert_equal '', @db.filename
|
41
41
|
tf = Tempfile.new 'thing'
|
42
42
|
@db.execute "ATTACH DATABASE '#{tf.path}' AS 'testing'"
|
43
|
-
|
43
|
+
|
44
|
+
assert_equal File.realdirpath(tf.path), File.realdirpath(@db.filename('testing'))
|
44
45
|
ensure
|
45
46
|
tf.unlink if tf
|
46
47
|
end
|
47
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
|
76
|
+
end
|
77
|
+
|
48
78
|
def test_bignum
|
49
79
|
num = 4907021672125087844
|
50
80
|
db.execute 'CREATE TABLE "employees" ("token" integer(8), "name" varchar(20) NOT NULL)'
|
@@ -66,15 +96,17 @@ module SQLite3
|
|
66
96
|
|
67
97
|
def test_get_first_row_with_type_translation_and_hash_results
|
68
98
|
@db.results_as_hash = true
|
69
|
-
|
99
|
+
@db.type_translation = true
|
100
|
+
assert_equal({"1"=>1}, @db.get_first_row('SELECT 1'))
|
70
101
|
end
|
71
102
|
|
72
103
|
def test_execute_with_type_translation_and_hash
|
73
104
|
@db.results_as_hash = true
|
105
|
+
@db.type_translation = true
|
74
106
|
rows = []
|
75
107
|
@db.execute('SELECT 1') { |row| rows << row }
|
76
108
|
|
77
|
-
assert_equal({
|
109
|
+
assert_equal({"1"=>1}, rows.first)
|
78
110
|
end
|
79
111
|
|
80
112
|
def test_encoding
|
@@ -101,6 +133,59 @@ module SQLite3
|
|
101
133
|
eosql
|
102
134
|
end
|
103
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
|
+
|
104
189
|
def test_new
|
105
190
|
db = SQLite3::Database.new(':memory:')
|
106
191
|
assert db
|
@@ -181,7 +266,7 @@ module SQLite3
|
|
181
266
|
db.execute("create table foo ( a integer primary key, b text )")
|
182
267
|
db.execute("insert into foo (b) values ('hello')")
|
183
268
|
rows = db.execute("select * from foo")
|
184
|
-
assert_equal [{
|
269
|
+
assert_equal [{"a"=>1, "b"=>"hello"}], rows
|
185
270
|
end
|
186
271
|
|
187
272
|
def test_execute_yields_hash
|
@@ -189,7 +274,7 @@ module SQLite3
|
|
189
274
|
db.execute("create table foo ( a integer primary key, b text )")
|
190
275
|
db.execute("insert into foo (b) values ('hello')")
|
191
276
|
db.execute("select * from foo") do |row|
|
192
|
-
assert_equal({
|
277
|
+
assert_equal({"a"=>1, "b"=>"hello"}, row)
|
193
278
|
end
|
194
279
|
end
|
195
280
|
|
@@ -276,7 +361,10 @@ module SQLite3
|
|
276
361
|
nil
|
277
362
|
end
|
278
363
|
@db.execute("select hello(2.2, 'foo', NULL)")
|
279
|
-
|
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])
|
280
368
|
end
|
281
369
|
|
282
370
|
def test_define_varargs
|
@@ -286,7 +374,10 @@ module SQLite3
|
|
286
374
|
nil
|
287
375
|
end
|
288
376
|
@db.execute("select hello(2.2, 'foo', NULL)")
|
289
|
-
|
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])
|
290
381
|
end
|
291
382
|
|
292
383
|
def test_call_func_blob
|
@@ -384,7 +475,7 @@ module SQLite3
|
|
384
475
|
def call action, a, b, c, d; nil end
|
385
476
|
}.new
|
386
477
|
stmt = @db.prepare("select 'fooooo'")
|
387
|
-
|
478
|
+
assert_nil stmt.step
|
388
479
|
end
|
389
480
|
|
390
481
|
def test_authorizer_fail
|
@@ -426,5 +517,29 @@ module SQLite3
|
|
426
517
|
def test_execute_with_named_bind_params
|
427
518
|
assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
|
428
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
|
537
|
+
|
538
|
+
def test_load_extension_with_nonstring_argument
|
539
|
+
db = SQLite3::Database.new(':memory:')
|
540
|
+
skip("extensions are not enabled") unless db.respond_to?(:load_extension)
|
541
|
+
assert_raises(TypeError) { db.load_extension(1) }
|
542
|
+
assert_raises(TypeError) { db.load_extension(Pathname.new("foo.so")) }
|
543
|
+
end
|
429
544
|
end
|
430
545
|
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
|
@@ -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
|
data/test/test_integration.rb
CHANGED
@@ -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,87 +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
|
-
|
503
|
-
# calling #get_first_value twice don't add up to the latest result
|
504
|
-
value = @db.get_first_value( "select accumulate(a) from foo" )
|
505
|
-
assert_equal 6, value
|
506
|
-
end
|
507
|
-
|
508
|
-
def test_create_aggregate_with_block
|
509
|
-
@db.create_aggregate( "accumulate", 1 ) do
|
510
|
-
step do |ctx,a|
|
511
|
-
ctx[:sum] ||= 0
|
512
|
-
ctx[:sum] += a.to_i
|
513
|
-
end
|
514
|
-
|
515
|
-
finalize { |ctx| ctx.result = ctx[:sum] }
|
516
|
-
end
|
517
|
-
|
518
|
-
value = @db.get_first_value( "select accumulate(a) from foo" )
|
519
|
-
assert_equal 6, value
|
520
|
-
end
|
521
|
-
|
522
|
-
def test_create_aggregate_with_no_data
|
523
|
-
@db.create_aggregate( "accumulate", 1 ) do
|
524
|
-
step do |ctx,a|
|
525
|
-
ctx[:sum] ||= 0
|
526
|
-
ctx[:sum] += a.to_i
|
527
|
-
end
|
528
|
-
|
529
|
-
finalize { |ctx| ctx.result = ctx[:sum] || 0 }
|
530
|
-
end
|
531
|
-
|
532
|
-
value = @db.get_first_value(
|
533
|
-
"select accumulate(a) from foo where a = 100" )
|
534
|
-
assert_equal 0, value
|
535
|
-
end
|
536
|
-
|
537
|
-
class AggregateHandler
|
538
|
-
class << self
|
539
|
-
def arity; 1; end
|
540
|
-
def text_rep; SQLite3::Constants::TextRep::ANY; end
|
541
|
-
def name; "multiply"; end
|
542
|
-
end
|
543
|
-
def step(ctx, a)
|
544
|
-
ctx[:buffer] ||= 1
|
545
|
-
ctx[:buffer] *= a.to_i
|
546
|
-
end
|
547
|
-
def finalize(ctx); ctx.result = ctx[:buffer]; end
|
548
|
-
end
|
549
|
-
|
550
|
-
def test_aggregate_initialized_twice
|
551
|
-
initialized = 0
|
552
|
-
handler = Class.new(AggregateHandler) do
|
553
|
-
define_method(:initialize) do
|
554
|
-
initialized += 1
|
555
|
-
super()
|
556
|
-
end
|
557
|
-
end
|
558
|
-
|
559
|
-
@db.create_aggregate_handler handler
|
560
|
-
@db.get_first_value( "select multiply(a) from foo" )
|
561
|
-
@db.get_first_value( "select multiply(a) from foo" )
|
562
|
-
assert_equal 2, initialized
|
563
|
-
end
|
564
|
-
|
565
|
-
def test_create_aggregate_handler
|
566
|
-
@db.create_aggregate_handler AggregateHandler
|
567
|
-
value = @db.get_first_value( "select multiply(a) from foo" )
|
568
|
-
assert_equal 6, value
|
569
|
-
end
|
570
|
-
|
571
502
|
def test_bind_array_parameter
|
572
503
|
result = @db.get_first_value( "select b from foo where a=? and b=?",
|
573
504
|
[ 1, "foo" ] )
|