sqlite3-full 1.3.9.1

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 (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/API_CHANGES.rdoc +50 -0
  4. data/CHANGELOG.rdoc +278 -0
  5. data/ChangeLog.cvs +88 -0
  6. data/Gemfile +15 -0
  7. data/LICENSE +34 -0
  8. data/Manifest.txt +52 -0
  9. data/README.rdoc +90 -0
  10. data/Rakefile +10 -0
  11. data/ext/sqlite3/backup.c +168 -0
  12. data/ext/sqlite3/backup.h +15 -0
  13. data/ext/sqlite3/database.c +825 -0
  14. data/ext/sqlite3/database.h +15 -0
  15. data/ext/sqlite3/exception.c +94 -0
  16. data/ext/sqlite3/exception.h +8 -0
  17. data/ext/sqlite3/extconf.rb +86 -0
  18. data/ext/sqlite3/sqlite3.c +97 -0
  19. data/ext/sqlite3/sqlite3_ruby.h +52 -0
  20. data/ext/sqlite3/sqlite3amalgamation.c +153367 -0
  21. data/ext/sqlite3/statement.c +447 -0
  22. data/ext/sqlite3/statement.h +16 -0
  23. data/faq/faq.rb +145 -0
  24. data/faq/faq.yml +426 -0
  25. data/lib/sqlite3/constants.rb +49 -0
  26. data/lib/sqlite3/database.rb +590 -0
  27. data/lib/sqlite3/errors.rb +44 -0
  28. data/lib/sqlite3/pragmas.rb +280 -0
  29. data/lib/sqlite3/resultset.rb +195 -0
  30. data/lib/sqlite3/statement.rb +144 -0
  31. data/lib/sqlite3/translator.rb +118 -0
  32. data/lib/sqlite3/value.rb +57 -0
  33. data/lib/sqlite3/version.rb +25 -0
  34. data/lib/sqlite3.rb +10 -0
  35. data/setup.rb +1333 -0
  36. data/tasks/faq.rake +9 -0
  37. data/tasks/gem.rake +38 -0
  38. data/tasks/native.rake +52 -0
  39. data/tasks/vendor_sqlite3.rake +91 -0
  40. data/test/helper.rb +18 -0
  41. data/test/test_backup.rb +33 -0
  42. data/test/test_collation.rb +82 -0
  43. data/test/test_database.rb +367 -0
  44. data/test/test_database_readonly.rb +29 -0
  45. data/test/test_deprecated.rb +44 -0
  46. data/test/test_encoding.rb +153 -0
  47. data/test/test_integration.rb +572 -0
  48. data/test/test_integration_open_close.rb +30 -0
  49. data/test/test_integration_pending.rb +115 -0
  50. data/test/test_integration_resultset.rb +159 -0
  51. data/test/test_integration_statement.rb +194 -0
  52. data/test/test_result_set.rb +37 -0
  53. data/test/test_sqlite3.rb +9 -0
  54. data/test/test_statement.rb +260 -0
  55. data/test/test_statement_execute.rb +35 -0
  56. metadata +205 -0
data/tasks/faq.rake ADDED
@@ -0,0 +1,9 @@
1
+ # Generate FAQ
2
+ desc "Generate the FAQ document"
3
+ task :faq => ['faq/faq.html']
4
+
5
+ file 'faq/faq.html' => ['faq/faq.rb', 'faq/faq.yml'] do
6
+ cd 'faq' do
7
+ ruby "faq.rb > faq.html"
8
+ end
9
+ end
data/tasks/gem.rake ADDED
@@ -0,0 +1,38 @@
1
+ begin
2
+ require 'hoe'
3
+ rescue LoadError
4
+ # try with rubygems?
5
+ require 'rubygems'
6
+ require 'hoe'
7
+ end
8
+
9
+ Hoe.plugin :debugging, :doofus, :git, :minitest, :bundler
10
+
11
+ HOE = Hoe.spec 'sqlite3-full' do
12
+ developer 'Jamis Buck', 'jamis@37signals.com'
13
+ developer 'Luis Lavena', 'luislavena@gmail.com'
14
+ developer 'Aaron Patterson', 'aaron@tenderlovemaking.com'
15
+ developer 'Eno Thierbach', 'eno@open-lab.org'
16
+
17
+ license "BSD-3"
18
+
19
+ self.readme_file = 'README.rdoc'
20
+ self.history_file = 'CHANGELOG.rdoc'
21
+ self.extra_rdoc_files = FileList['*.rdoc', 'ext/**/*.c']
22
+
23
+ require_ruby_version ">= 1.8.7"
24
+ require_rubygems_version ">= 1.3.5"
25
+
26
+ spec_extras[:extensions] = ["ext/sqlite3/extconf.rb"]
27
+
28
+ extra_dev_deps << ['rake-compiler', "~> 0.9.3"]
29
+ extra_dev_deps << ["mini_portile", "~> 0.6.1"]
30
+ extra_dev_deps << ["minitest", "~> 5.0"]
31
+ extra_dev_deps << ["hoe-bundler", "~> 1.0"]
32
+
33
+ clean_globs.push('**/test.db')
34
+ end
35
+
36
+ Hoe.add_include_dirs '.'
37
+
38
+ # vim: syntax=ruby
data/tasks/native.rake ADDED
@@ -0,0 +1,52 @@
1
+ # use rake-compiler for building the extension
2
+ require 'rake/extensiontask'
3
+ require 'rake/extensioncompiler'
4
+
5
+ # NOTE: version used by cross compilation of Windows native extension
6
+ # It do not affect compilation under other operating systems
7
+ # The version indicated is the minimum DLL suggested for correct functionality
8
+ BINARY_VERSION = "3.8.6"
9
+ URL_VERSION = "3080600"
10
+ URL_PATH = "/2014"
11
+
12
+ task :devkit do
13
+ begin
14
+ require "devkit"
15
+ rescue LoadError => e
16
+ abort "Failed to activate RubyInstaller's DevKit required for compilation."
17
+ end
18
+ end
19
+
20
+ # build sqlite3_native C extension
21
+ RUBY_EXTENSION = Rake::ExtensionTask.new('sqlite3_native', HOE.spec) do |ext|
22
+ # where to locate the extension
23
+ ext.ext_dir = 'ext/sqlite3'
24
+
25
+ # where native extension will be copied (matches makefile)
26
+ ext.lib_dir = "lib/sqlite3"
27
+
28
+ # clean binary folders always
29
+ CLEAN.include("#{ext.lib_dir}/?.?")
30
+
31
+ # automatically add build options to avoid need of manual input
32
+ if RUBY_PLATFORM =~ /mswin|mingw/ then
33
+ # define target for extension (supporting fat binaries)
34
+ RUBY_VERSION =~ /(\d+\.\d+)/
35
+ ext.lib_dir = "lib/sqlite3/#{$1}"
36
+ else
37
+
38
+ # detect cross-compiler available
39
+ begin
40
+ Rake::ExtensionCompiler.mingw_host
41
+ ext.cross_compile = true
42
+ ext.cross_platform = ['i386-mswin32-60', 'i386-mingw32', 'x64-mingw32']
43
+ rescue RuntimeError
44
+ # noop
45
+ end
46
+ end
47
+ end
48
+
49
+ # ensure things are compiled prior testing
50
+ task :test => [:compile]
51
+
52
+ # vim: syntax=ruby
@@ -0,0 +1,91 @@
1
+ require "rake/clean"
2
+ require "rake/extensioncompiler"
3
+ require "mini_portile"
4
+
5
+ CLOBBER.include("ports")
6
+
7
+ directory "ports"
8
+
9
+ def define_sqlite_task(platform, host)
10
+ recipe = MiniPortile.new "sqlite3", BINARY_VERSION
11
+ recipe.files << "http://sqlite.org#{URL_PATH}/sqlite-autoconf-#{URL_VERSION}.tar.gz"
12
+ recipe.host = host
13
+
14
+ desc "Compile sqlite3 for #{platform} (#{host})"
15
+ task "ports:sqlite3:#{platform}" => ["ports"] do |t|
16
+ checkpoint = "ports/.#{recipe.name}-#{recipe.version}-#{recipe.host}.installed"
17
+
18
+ unless File.exist?(checkpoint)
19
+ cflags = "-O2 -DSQLITE_ENABLE_COLUMN_METADATA"
20
+ cflags << " -fPIC" if recipe.host && recipe.host.include?("x86_64")
21
+ recipe.configure_options << "CFLAGS='#{cflags}'"
22
+ recipe.cook
23
+ touch checkpoint
24
+ end
25
+ end
26
+
27
+ recipe
28
+ end
29
+
30
+ # native sqlite3 compilation
31
+ recipe = define_sqlite_task(RUBY_PLATFORM, RbConfig::CONFIG["host"])
32
+
33
+ # force compilation of sqlite3 when working natively under MinGW
34
+ if RUBY_PLATFORM =~ /mingw/
35
+ RUBY_EXTENSION.config_options << "--with-opt-dir=#{recipe.path}"
36
+
37
+ # also prepend DevKit into compilation phase
38
+ Rake::Task["compile"].prerequisites.unshift "devkit", "ports:sqlite3:#{RUBY_PLATFORM}"
39
+ Rake::Task["native"].prerequisites.unshift "devkit", "ports:sqlite3:#{RUBY_PLATFORM}"
40
+ end
41
+
42
+ # trick to test local compilation of sqlite3
43
+ if ENV["USE_MINI_PORTILE"] == "true"
44
+ # fake recipe so we can build a directory to it
45
+ recipe = MiniPortile.new "sqlite3", BINARY_VERSION
46
+ recipe.host = RbConfig::CONFIG["host"]
47
+
48
+ RUBY_EXTENSION.config_options << "--with-opt-dir=#{recipe.path}"
49
+
50
+ # compile sqlite3 first
51
+ Rake::Task["compile"].prerequisites.unshift "ports:sqlite3:#{RUBY_PLATFORM}"
52
+ end
53
+
54
+ # iterate over all cross-compilation platforms and define the proper
55
+ # sqlite3 recipe for it.
56
+ if RUBY_EXTENSION.cross_compile
57
+ config_path = File.expand_path("~/.rake-compiler/config.yml")
58
+ if File.exist?(config_path)
59
+ # obtains platforms from rake-compiler's config.yml
60
+ config_file = YAML.load_file(config_path)
61
+
62
+ Array(RUBY_EXTENSION.cross_platform).each do |platform|
63
+ # obtain platform from rbconfig file
64
+ config_key = config_file.keys.sort.find { |key|
65
+ key.start_with?("rbconfig-#{platform}-")
66
+ }
67
+ rbfile = config_file[config_key]
68
+
69
+ # skip if rbconfig cannot be read
70
+ next unless File.exist?(rbfile)
71
+
72
+ host = IO.read(rbfile).match(/CONFIG\["CC"\] = "(.*)"/)[1].sub(/\-gcc/, '')
73
+ recipe = define_sqlite_task(platform, host)
74
+
75
+ RUBY_EXTENSION.cross_config_options << {
76
+ platform => "--with-opt-dir=#{recipe.path}"
77
+ }
78
+
79
+ # pre-compile sqlite3 port when cross-compiling
80
+ task :cross => "ports:sqlite3:#{platform}"
81
+ end
82
+ else
83
+ warn "rake-compiler configuration doesn't exist, but is required for ports"
84
+ end
85
+ end
86
+
87
+ task :cross do
88
+ ["CC", "CXX", "LDFLAGS", "CPPFLAGS", "RUBYOPT"].each do |var|
89
+ ENV.delete(var)
90
+ end
91
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'sqlite3'
2
+ require 'minitest/autorun'
3
+
4
+ unless RUBY_VERSION >= "1.9"
5
+ require 'iconv'
6
+ end
7
+
8
+ module SQLite3
9
+ class TestCase < Minitest::Test
10
+ alias :assert_not_equal :refute_equal
11
+ alias :assert_not_nil :refute_nil
12
+ alias :assert_raise :assert_raises
13
+
14
+ def assert_nothing_raised
15
+ yield
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,33 @@
1
+ require 'helper'
2
+
3
+ module SQLite3
4
+ class TestBackup < SQLite3::TestCase
5
+ def setup
6
+ @sdb = SQLite3::Database.new(':memory:')
7
+ @ddb = SQLite3::Database.new(':memory:')
8
+ @sdb.execute('CREATE TABLE foo (idx, val);');
9
+ @data = ('A'..'Z').map{|x|x * 40}
10
+ @data.each_with_index do |v, i|
11
+ @sdb.execute('INSERT INTO foo (idx, val) VALUES (?, ?);', [i, v])
12
+ end
13
+ end
14
+
15
+ def test_backup_step
16
+ b = SQLite3::Backup.new(@ddb, 'main', @sdb, 'main')
17
+ while b.step(1) == SQLite3::Constants::ErrorCode::OK
18
+ assert_not_equal(0, b.remaining)
19
+ end
20
+ assert_equal(0, b.remaining)
21
+ b.finish
22
+ assert_equal(@data.length, @ddb.execute('SELECT * FROM foo;').length)
23
+ end
24
+
25
+ def test_backup_all
26
+ b = SQLite3::Backup.new(@ddb, 'main', @sdb, 'main')
27
+ assert_equal(SQLite3::Constants::ErrorCode::DONE, b.step(-1))
28
+ assert_equal(0, b.remaining)
29
+ b.finish
30
+ assert_equal(@data.length, @ddb.execute('SELECT * FROM foo;').length)
31
+ end
32
+ end if defined?(SQLite3::Backup)
33
+ end
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'helper'
4
+
5
+ module SQLite3
6
+ class TestCollation < SQLite3::TestCase
7
+ class Comparator
8
+ attr_reader :calls
9
+ def initialize
10
+ @calls = []
11
+ end
12
+
13
+ def compare left, right
14
+ @calls << [left, right]
15
+ left <=> right
16
+ end
17
+ end
18
+
19
+ def setup
20
+ @db = SQLite3::Database.new(':memory:')
21
+ @create = "create table ex(id int, data string)"
22
+ @db.execute(@create);
23
+ [ [1, 'hello'], [2, 'world'] ].each do |vals|
24
+ @db.execute('insert into ex (id, data) VALUES (?, ?)', vals)
25
+ end
26
+ end
27
+
28
+ def test_custom_collation
29
+ comparator = Comparator.new
30
+
31
+ @db.collation 'foo', comparator
32
+
33
+ assert_equal comparator, @db.collations['foo']
34
+ @db.execute('select data from ex order by 1 collate foo')
35
+ assert_equal 1, comparator.calls.length
36
+ end
37
+
38
+ def test_remove_collation
39
+ comparator = Comparator.new
40
+
41
+ @db.collation 'foo', comparator
42
+ @db.collation 'foo', nil
43
+
44
+ assert_nil @db.collations['foo']
45
+ assert_raises(SQLite3::SQLException) do
46
+ @db.execute('select data from ex order by 1 collate foo')
47
+ end
48
+ end
49
+
50
+ if RUBY_VERSION >= '1.9.1'
51
+ def test_encoding
52
+ comparator = Comparator.new
53
+ @db.collation 'foo', comparator
54
+ @db.execute('select data from ex order by 1 collate foo')
55
+
56
+ a, b = *comparator.calls.first
57
+
58
+ assert_equal Encoding.find('UTF-8'), a.encoding
59
+ assert_equal Encoding.find('UTF-8'), b.encoding
60
+ end
61
+
62
+ def test_encoding_default_internal
63
+ warn_before = $-w
64
+ $-w = false
65
+ before_enc = Encoding.default_internal
66
+
67
+ Encoding.default_internal = 'EUC-JP'
68
+ comparator = Comparator.new
69
+ @db.collation 'foo', comparator
70
+ @db.execute('select data from ex order by 1 collate foo')
71
+
72
+ a, b = *comparator.calls.first
73
+
74
+ assert_equal Encoding.find('EUC-JP'), a.encoding
75
+ assert_equal Encoding.find('EUC-JP'), b.encoding
76
+ ensure
77
+ Encoding.default_internal = before_enc
78
+ $-w = warn_before
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,367 @@
1
+ require 'helper'
2
+
3
+ module SQLite3
4
+ class TestDatabase < SQLite3::TestCase
5
+ attr_reader :db
6
+
7
+ def setup
8
+ @db = SQLite3::Database.new(':memory:')
9
+ end
10
+
11
+ def test_segv
12
+ assert_raises(TypeError) { SQLite3::Database.new 1 }
13
+ end
14
+
15
+ def test_bignum
16
+ num = 4907021672125087844
17
+ db.execute 'CREATE TABLE "employees" ("token" integer(8), "name" varchar(20) NOT NULL)'
18
+ db.execute "INSERT INTO employees(name, token) VALUES('employee-1', ?)", [num]
19
+ rows = db.execute 'select token from employees'
20
+ assert_equal num, rows.first.first
21
+ end
22
+
23
+ def test_blob
24
+ @db.execute("CREATE TABLE blobs ( id INTEGER, hash BLOB(10) )")
25
+ blob = Blob.new("foo\0bar")
26
+ @db.execute("INSERT INTO blobs VALUES (0, ?)", [blob])
27
+ assert_equal [[0, blob, blob.length, blob.length*2]], @db.execute("SELECT id, hash, length(hash), length(hex(hash)) FROM blobs")
28
+ end
29
+
30
+ def test_get_first_row
31
+ assert_equal [1], @db.get_first_row('SELECT 1')
32
+ end
33
+
34
+ def test_get_first_row_with_type_translation_and_hash_results
35
+ @db.results_as_hash = true
36
+ assert_equal({0=>1, "1"=>1}, @db.get_first_row('SELECT 1'))
37
+ end
38
+
39
+ def test_execute_with_type_translation_and_hash
40
+ @db.results_as_hash = true
41
+ rows = []
42
+ @db.execute('SELECT 1') { |row| rows << row }
43
+
44
+ assert_equal({0=>1, "1"=>1}, rows.first)
45
+ end
46
+
47
+ def test_encoding
48
+ assert @db.encoding, 'database has encoding'
49
+ end
50
+
51
+ def test_changes
52
+ @db.execute("CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT, number integer)")
53
+ assert_equal 0, @db.changes
54
+ @db.execute("INSERT INTO items (number) VALUES (10)")
55
+ assert_equal 1, @db.changes
56
+ @db.execute_batch(
57
+ "UPDATE items SET number = (number + :nn) WHERE (number = :n)",
58
+ {"nn" => 20, "n" => 10})
59
+ assert_equal 1, @db.changes
60
+ assert_equal [[30]], @db.execute("select number from items")
61
+ end
62
+
63
+ def test_batch_last_comment_is_processed
64
+ # FIXME: nil as a successful return value is kinda dumb
65
+ assert_nil @db.execute_batch <<-eosql
66
+ CREATE TABLE items (id integer PRIMARY KEY AUTOINCREMENT);
67
+ -- omg
68
+ eosql
69
+ end
70
+
71
+ def test_new
72
+ db = SQLite3::Database.new(':memory:')
73
+ assert db
74
+ end
75
+
76
+ def test_new_yields_self
77
+ thing = nil
78
+ SQLite3::Database.new(':memory:') do |db|
79
+ thing = db
80
+ end
81
+ assert_instance_of(SQLite3::Database, thing)
82
+ end
83
+
84
+ def test_new_with_options
85
+ # determine if Ruby is running on Big Endian platform
86
+ utf16 = ([1].pack("I") == [1].pack("N")) ? "UTF-16BE" : "UTF-16LE"
87
+
88
+ if RUBY_VERSION >= "1.9"
89
+ db = SQLite3::Database.new(':memory:'.encode(utf16), :utf16 => true)
90
+ else
91
+ db = SQLite3::Database.new(Iconv.conv(utf16, 'UTF-8', ':memory:'),
92
+ :utf16 => true)
93
+ end
94
+ assert db
95
+ end
96
+
97
+ def test_close
98
+ db = SQLite3::Database.new(':memory:')
99
+ db.close
100
+ assert db.closed?
101
+ end
102
+
103
+ def test_block_closes_self
104
+ thing = nil
105
+ SQLite3::Database.new(':memory:') do |db|
106
+ thing = db
107
+ assert !thing.closed?
108
+ end
109
+ assert thing.closed?
110
+ end
111
+
112
+ def test_prepare
113
+ db = SQLite3::Database.new(':memory:')
114
+ stmt = db.prepare('select "hello world"')
115
+ assert_instance_of(SQLite3::Statement, stmt)
116
+ end
117
+
118
+ def test_block_prepare_does_not_double_close
119
+ db = SQLite3::Database.new(':memory:')
120
+ r = db.prepare('select "hello world"') do |stmt|
121
+ stmt.close
122
+ :foo
123
+ end
124
+ assert_equal :foo, r
125
+ end
126
+
127
+ def test_total_changes
128
+ db = SQLite3::Database.new(':memory:')
129
+ db.execute("create table foo ( a integer primary key, b text )")
130
+ db.execute("insert into foo (b) values ('hello')")
131
+ assert_equal 1, db.total_changes
132
+ end
133
+
134
+ def test_execute_returns_list_of_hash
135
+ db = SQLite3::Database.new(':memory:', :results_as_hash => true)
136
+ db.execute("create table foo ( a integer primary key, b text )")
137
+ db.execute("insert into foo (b) values ('hello')")
138
+ rows = db.execute("select * from foo")
139
+ assert_equal [{0=>1, "a"=>1, "b"=>"hello", 1=>"hello"}], rows
140
+ end
141
+
142
+ def test_execute_yields_hash
143
+ db = SQLite3::Database.new(':memory:', :results_as_hash => true)
144
+ db.execute("create table foo ( a integer primary key, b text )")
145
+ db.execute("insert into foo (b) values ('hello')")
146
+ db.execute("select * from foo") do |row|
147
+ assert_equal({0=>1, "a"=>1, "b"=>"hello", 1=>"hello"}, row)
148
+ end
149
+ end
150
+
151
+ def test_table_info
152
+ db = SQLite3::Database.new(':memory:', :results_as_hash => true)
153
+ db.execute("create table foo ( a integer primary key, b text )")
154
+ info = [{
155
+ "name" => "a",
156
+ "pk" => 1,
157
+ "notnull" => 0,
158
+ "type" => "integer",
159
+ "dflt_value" => nil,
160
+ "cid" => 0
161
+ },
162
+ {
163
+ "name" => "b",
164
+ "pk" => 0,
165
+ "notnull" => 0,
166
+ "type" => "text",
167
+ "dflt_value" => nil,
168
+ "cid" => 1
169
+ }]
170
+ assert_equal info, db.table_info('foo')
171
+ end
172
+
173
+ def test_total_changes_closed
174
+ db = SQLite3::Database.new(':memory:')
175
+ db.close
176
+ assert_raise(SQLite3::Exception) do
177
+ db.total_changes
178
+ end
179
+ end
180
+
181
+ def test_trace_requires_opendb
182
+ @db.close
183
+ assert_raise(SQLite3::Exception) do
184
+ @db.trace { |x| }
185
+ end
186
+ end
187
+
188
+ def test_trace_with_block
189
+ result = nil
190
+ @db.trace { |sql| result = sql }
191
+ @db.execute "select 'foo'"
192
+ assert_equal "select 'foo'", result
193
+ end
194
+
195
+ def test_trace_with_object
196
+ obj = Class.new {
197
+ attr_accessor :result
198
+ def call sql; @result = sql end
199
+ }.new
200
+
201
+ @db.trace(obj)
202
+ @db.execute "select 'foo'"
203
+ assert_equal "select 'foo'", obj.result
204
+ end
205
+
206
+ def test_trace_takes_nil
207
+ @db.trace(nil)
208
+ @db.execute "select 'foo'"
209
+ end
210
+
211
+ def test_last_insert_row_id_closed
212
+ @db.close
213
+ assert_raise(SQLite3::Exception) do
214
+ @db.last_insert_row_id
215
+ end
216
+ end
217
+
218
+ def test_define_function
219
+ called_with = nil
220
+ @db.define_function("hello") do |value|
221
+ called_with = value
222
+ end
223
+ @db.execute("select hello(10)")
224
+ assert_equal 10, called_with
225
+ end
226
+
227
+ def test_call_func_arg_type
228
+ called_with = nil
229
+ @db.define_function("hello") do |b, c, d|
230
+ called_with = [b, c, d]
231
+ nil
232
+ end
233
+ @db.execute("select hello(2.2, 'foo', NULL)")
234
+ assert_equal [2.2, 'foo', nil], called_with
235
+ end
236
+
237
+ def test_define_varargs
238
+ called_with = nil
239
+ @db.define_function("hello") do |*args|
240
+ called_with = args
241
+ nil
242
+ end
243
+ @db.execute("select hello(2.2, 'foo', NULL)")
244
+ assert_equal [2.2, 'foo', nil], called_with
245
+ end
246
+
247
+ def test_call_func_blob
248
+ called_with = nil
249
+ @db.define_function("hello") do |a, b|
250
+ called_with = [a, b, a.length]
251
+ nil
252
+ end
253
+ blob = Blob.new("a\0fine\0kettle\0of\0fish")
254
+ @db.execute("select hello(?, length(?))", [blob, blob])
255
+ assert_equal [blob, blob.length, 21], called_with
256
+ end
257
+
258
+ def test_function_return
259
+ @db.define_function("hello") { |a| 10 }
260
+ assert_equal [10], @db.execute("select hello('world')").first
261
+ end
262
+
263
+ def test_function_return_types
264
+ [10, 2.2, nil, "foo"].each do |thing|
265
+ @db.define_function("hello") { |a| thing }
266
+ assert_equal [thing], @db.execute("select hello('world')").first
267
+ end
268
+ end
269
+
270
+ def test_define_function_closed
271
+ @db.close
272
+ assert_raise(SQLite3::Exception) do
273
+ @db.define_function('foo') { }
274
+ end
275
+ end
276
+
277
+ def test_inerrupt_closed
278
+ @db.close
279
+ assert_raise(SQLite3::Exception) do
280
+ @db.interrupt
281
+ end
282
+ end
283
+
284
+ def test_define_aggregate
285
+ @db.execute "create table foo ( a integer primary key, b text )"
286
+ @db.execute "insert into foo ( b ) values ( 'foo' )"
287
+ @db.execute "insert into foo ( b ) values ( 'bar' )"
288
+ @db.execute "insert into foo ( b ) values ( 'baz' )"
289
+
290
+ acc = Class.new {
291
+ attr_reader :sum
292
+ alias :finalize :sum
293
+ def initialize
294
+ @sum = 0
295
+ end
296
+
297
+ def step a
298
+ @sum += a
299
+ end
300
+ }.new
301
+
302
+ @db.define_aggregator("accumulate", acc)
303
+ value = @db.get_first_value( "select accumulate(a) from foo" )
304
+ assert_equal 6, value
305
+ end
306
+
307
+ def test_authorizer_ok
308
+ @db.authorizer = Class.new {
309
+ def call action, a, b, c, d; true end
310
+ }.new
311
+ @db.prepare("select 'fooooo'")
312
+
313
+ @db.authorizer = Class.new {
314
+ def call action, a, b, c, d; 0 end
315
+ }.new
316
+ @db.prepare("select 'fooooo'")
317
+ end
318
+
319
+ def test_authorizer_ignore
320
+ @db.authorizer = Class.new {
321
+ def call action, a, b, c, d; nil end
322
+ }.new
323
+ stmt = @db.prepare("select 'fooooo'")
324
+ assert_equal nil, stmt.step
325
+ end
326
+
327
+ def test_authorizer_fail
328
+ @db.authorizer = Class.new {
329
+ def call action, a, b, c, d; false end
330
+ }.new
331
+ assert_raises(SQLite3::AuthorizationException) do
332
+ @db.prepare("select 'fooooo'")
333
+ end
334
+ end
335
+
336
+ def test_remove_auth
337
+ @db.authorizer = Class.new {
338
+ def call action, a, b, c, d; false end
339
+ }.new
340
+ assert_raises(SQLite3::AuthorizationException) do
341
+ @db.prepare("select 'fooooo'")
342
+ end
343
+
344
+ @db.authorizer = nil
345
+ @db.prepare("select 'fooooo'")
346
+ end
347
+
348
+ def test_close_with_open_statements
349
+ @db.prepare("select 'foo'")
350
+ assert_raises(SQLite3::BusyException) do
351
+ @db.close
352
+ end
353
+ end
354
+
355
+ def test_execute_with_empty_bind_params
356
+ assert_equal [['foo']], @db.execute("select 'foo'", [])
357
+ end
358
+
359
+ def test_query_with_named_bind_params
360
+ assert_equal [['foo']], @db.query("select :n", {'n' => 'foo'}).to_a
361
+ end
362
+
363
+ def test_execute_with_named_bind_params
364
+ assert_equal [['foo']], @db.execute("select :n", {'n' => 'foo'})
365
+ end
366
+ end
367
+ end