sqlite3 1.7.2 → 2.7.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +323 -1
  3. data/CONTRIBUTING.md +33 -7
  4. data/FAQ.md +43 -77
  5. data/INSTALLATION.md +14 -6
  6. data/LICENSE +18 -22
  7. data/README.md +97 -9
  8. data/dependencies.yml +10 -11
  9. data/ext/sqlite3/aggregator.c +142 -145
  10. data/ext/sqlite3/aggregator.h +2 -4
  11. data/ext/sqlite3/backup.c +74 -65
  12. data/ext/sqlite3/backup.h +2 -2
  13. data/ext/sqlite3/database.c +623 -495
  14. data/ext/sqlite3/database.h +13 -4
  15. data/ext/sqlite3/exception.c +116 -92
  16. data/ext/sqlite3/exception.h +5 -1
  17. data/ext/sqlite3/extconf.rb +32 -24
  18. data/ext/sqlite3/sqlite3.c +176 -115
  19. data/ext/sqlite3/sqlite3_ruby.h +2 -2
  20. data/ext/sqlite3/statement.c +553 -300
  21. data/ext/sqlite3/statement.h +4 -3
  22. data/ext/sqlite3/timespec.h +20 -0
  23. data/lib/sqlite3/constants.rb +195 -47
  24. data/lib/sqlite3/database.rb +224 -187
  25. data/lib/sqlite3/errors.rb +54 -1
  26. data/lib/sqlite3/fork_safety.rb +66 -0
  27. data/lib/sqlite3/pragmas.rb +194 -141
  28. data/lib/sqlite3/resultset.rb +14 -97
  29. data/lib/sqlite3/statement.rb +58 -13
  30. data/lib/sqlite3/value.rb +17 -20
  31. data/lib/sqlite3/version.rb +2 -21
  32. data/lib/sqlite3/version_info.rb +17 -0
  33. data/lib/sqlite3.rb +8 -4
  34. data/ports/archives/sqlite-autoconf-3500100.tar.gz +0 -0
  35. metadata +9 -37
  36. data/API_CHANGES.md +0 -49
  37. data/ChangeLog.cvs +0 -88
  38. data/Gemfile +0 -10
  39. data/LICENSE-DEPENDENCIES +0 -20
  40. data/lib/sqlite3/translator.rb +0 -117
  41. data/ports/archives/sqlite-autoconf-3450100.tar.gz +0 -0
  42. data/test/helper.rb +0 -27
  43. data/test/test_backup.rb +0 -33
  44. data/test/test_collation.rb +0 -82
  45. data/test/test_database.rb +0 -668
  46. data/test/test_database_flags.rb +0 -95
  47. data/test/test_database_readonly.rb +0 -36
  48. data/test/test_database_readwrite.rb +0 -41
  49. data/test/test_deprecated.rb +0 -49
  50. data/test/test_encoding.rb +0 -165
  51. data/test/test_integration.rb +0 -507
  52. data/test/test_integration_aggregate.rb +0 -336
  53. data/test/test_integration_open_close.rb +0 -30
  54. data/test/test_integration_pending.rb +0 -115
  55. data/test/test_integration_resultset.rb +0 -142
  56. data/test/test_integration_statement.rb +0 -194
  57. data/test/test_pragmas.rb +0 -22
  58. data/test/test_result_set.rb +0 -47
  59. data/test/test_sqlite3.rb +0 -30
  60. data/test/test_statement.rb +0 -290
  61. data/test/test_statement_execute.rb +0 -39
@@ -1,14 +1,17 @@
1
- require 'sqlite3/constants'
2
- require 'sqlite3/errors'
3
- require 'sqlite3/pragmas'
4
- require 'sqlite3/statement'
5
- require 'sqlite3/translator'
6
- require 'sqlite3/value'
1
+ # frozen_string_literal: true
7
2
 
8
- module SQLite3
3
+ require "sqlite3/constants"
4
+ require "sqlite3/errors"
5
+ require "sqlite3/pragmas"
6
+ require "sqlite3/statement"
7
+ require "sqlite3/value"
8
+ require "sqlite3/fork_safety"
9
9
 
10
- # The Database class encapsulates a single connection to a SQLite3 database.
11
- # Its usage is very straightforward:
10
+ module SQLite3
11
+ # == Overview
12
+ #
13
+ # The Database class encapsulates a single connection to a SQLite3 database. Here's a
14
+ # straightforward example of usage:
12
15
  #
13
16
  # require 'sqlite3'
14
17
  #
@@ -18,31 +21,79 @@ module SQLite3
18
21
  # end
19
22
  # end
20
23
  #
21
- # It wraps the lower-level methods provided by the selected driver, and
22
- # includes the Pragmas module for access to various pragma convenience
23
- # methods.
24
+ # It wraps the lower-level methods provided by the selected driver, and includes the Pragmas
25
+ # module for access to various pragma convenience methods.
24
26
  #
25
- # The Database class provides type translation services as well, by which
26
- # the SQLite3 data types (which are all represented as strings) may be
27
- # converted into their corresponding types (as defined in the schemas
28
- # for their tables). This translation only occurs when querying data from
27
+ # The Database class provides type translation services as well, by which the SQLite3 data types
28
+ # (which are all represented as strings) may be converted into their corresponding types (as
29
+ # defined in the schemas for their tables). This translation only occurs when querying data from
29
30
  # the database--insertions and updates are all still typeless.
30
31
  #
31
- # Furthermore, the Database class has been designed to work well with the
32
- # ArrayFields module from Ara Howard. If you require the ArrayFields
33
- # module before performing a query, and if you have not enabled results as
34
- # hashes, then the results will all be indexible by field name.
32
+ # Furthermore, the Database class has been designed to work well with the ArrayFields module from
33
+ # Ara Howard. If you require the ArrayFields module before performing a query, and if you have not
34
+ # enabled results as hashes, then the results will all be indexible by field name.
35
+ #
36
+ # == Thread safety
37
+ #
38
+ # When SQLite3.threadsafe? returns true, it is safe to share instances of the database class
39
+ # among threads without adding specific locking. Other object instances may require applications
40
+ # to provide their own locks if they are to be shared among threads. Please see the README.md for
41
+ # more information.
42
+ #
43
+ # == SQLite Extensions
44
+ #
45
+ # SQLite3::Database supports the universe of {sqlite
46
+ # extensions}[https://www.sqlite.org/loadext.html]. It's possible to load an extension into an
47
+ # existing Database object using the #load_extension method and passing a filesystem path:
48
+ #
49
+ # db = SQLite3::Database.new(":memory:")
50
+ # db.enable_load_extension(true)
51
+ # db.load_extension("/path/to/extension")
52
+ #
53
+ # As of v2.4.0, it's also possible to pass an object that responds to +#to_path+. This
54
+ # documentation will refer to the supported interface as +_ExtensionSpecifier+, which can be
55
+ # expressed in RBS syntax as:
56
+ #
57
+ # interface _ExtensionSpecifier
58
+ # def to_path: () → String
59
+ # end
60
+ #
61
+ # So, for example, if you are using the {sqlean gem}[https://github.com/flavorjones/sqlean-ruby]
62
+ # which provides modules that implement this interface, you can pass the module directly:
63
+ #
64
+ # db = SQLite3::Database.new(":memory:")
65
+ # db.enable_load_extension(true)
66
+ # db.load_extension(SQLean::Crypto)
67
+ #
68
+ # It's also possible in v2.4.0+ to load extensions via the SQLite3::Database constructor by using
69
+ # the +extensions:+ keyword argument to pass an array of String paths or extension specifiers:
70
+ #
71
+ # db = SQLite3::Database.new(":memory:", extensions: ["/path/to/extension", SQLean::Crypto])
72
+ #
73
+ # Note that when loading extensions via the constructor, there is no need to call
74
+ # #enable_load_extension; however it is still necessary to call #enable_load_extensions before any
75
+ # subsequently invocations of #load_extension on the initialized Database object.
76
+ #
77
+ # You can load extensions in a Rails application by using the +extensions:+ configuration option:
78
+ #
79
+ # # config/database.yml
80
+ # development:
81
+ # adapter: sqlite3
82
+ # extensions:
83
+ # - .sqlpkg/nalgeon/crypto/crypto.so # a filesystem path
84
+ # - <%= SQLean::UUID.to_path %> # or ruby code returning a path
85
+ # - SQLean::Crypto # Rails 8.1+ accepts the name of a constant that responds to `to_path`
86
+ #
35
87
  class Database
36
88
  attr_reader :collations
37
89
 
38
90
  include Pragmas
39
91
 
40
92
  class << self
41
-
42
93
  # Without block works exactly as new.
43
94
  # With block, like new closes the database at the end, but unlike new
44
95
  # returns the result of the block instead of the database instance.
45
- def open( *args )
96
+ def open(*args)
46
97
  database = new(*args)
47
98
 
48
99
  if block_given?
@@ -59,34 +110,34 @@ module SQLite3
59
110
  # Quotes the given string, making it safe to use in an SQL statement.
60
111
  # It replaces all instances of the single-quote character with two
61
112
  # single-quote characters. The modified string is returned.
62
- def quote( string )
63
- string.gsub( /'/, "''" )
113
+ def quote(string)
114
+ string.gsub("'", "''")
64
115
  end
65
-
66
116
  end
67
117
 
68
118
  # A boolean that indicates whether rows in result sets should be returned
69
119
  # as hashes or not. By default, rows are returned as arrays.
70
120
  attr_accessor :results_as_hash
71
121
 
72
- # call-seq: SQLite3::Database.new(file, options = {})
122
+ # call-seq:
123
+ # SQLite3::Database.new(file, options = {})
73
124
  #
74
125
  # Create a new Database object that opens the given file.
75
126
  #
76
127
  # Supported permissions +options+:
77
128
  # - the default mode is <tt>READWRITE | CREATE</tt>
78
- # - +:readonly+: boolean (default false), true to set the mode to +READONLY+
79
- # - +:readwrite+: boolean (default false), true to set the mode to +READWRITE+
80
- # - +:flags+: set the mode to a combination of SQLite3::Constants::Open flags.
129
+ # - +readonly:+ boolean (default false), true to set the mode to +READONLY+
130
+ # - +readwrite:+ boolean (default false), true to set the mode to +READWRITE+
131
+ # - +flags:+ set the mode to a combination of SQLite3::Constants::Open flags.
81
132
  #
82
133
  # Supported encoding +options+:
83
- # - +:utf16+: boolean (default false), is the filename's encoding UTF-16 (only needed if the filename encoding is not UTF_16LE or BE)
134
+ # - +utf16:+ +boolish+ (default false), is the filename's encoding UTF-16 (only needed if the filename encoding is not UTF_16LE or BE)
84
135
  #
85
136
  # Other supported +options+:
86
- # - +:strict+: boolean (default false), disallow the use of double-quoted string literals (see https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted)
87
- # - +:results_as_hash+: boolean (default false), return rows as hashes instead of arrays
88
- # - +:type_translation+: boolean (default false), enable type translation
89
- # - +:default_transaction_mode+: one of +:deferred+ (default), +:immediate+, or +:exclusive+. If a mode is not specified in a call to #transaction, this will be the default transaction mode.
137
+ # - +strict:+ +boolish+ (default false), disallow the use of double-quoted string literals (see https://www.sqlite.org/quirks.html#double_quoted_string_literals_are_accepted)
138
+ # - +results_as_hash:+ +boolish+ (default false), return rows as hashes instead of arrays
139
+ # - +default_transaction_mode:+ one of +:deferred+ (default), +:immediate+, or +:exclusive+. If a mode is not specified in a call to #transaction, this will be the default transaction mode.
140
+ # - +extensions:+ <tt>Array[String | _ExtensionSpecifier]</tt> SQLite extensions to load into the database. See Database@SQLite+Extensions for more information.
90
141
  #
91
142
  def initialize file, options = {}, zvfs = nil
92
143
  mode = Constants::Open::READWRITE | Constants::Open::CREATE
@@ -120,18 +171,19 @@ module SQLite3
120
171
  end
121
172
  end
122
173
 
123
- @tracefunc = nil
124
- @authorizer = nil
125
- @encoding = nil
126
- @busy_handler = nil
127
- @collations = {}
128
- @functions = {}
129
- @results_as_hash = options[:results_as_hash]
130
- @type_translation = options[:type_translation]
131
- @type_translator = make_type_translator @type_translation
132
- @readonly = mode & Constants::Open::READONLY != 0
174
+ @tracefunc = nil
175
+ @authorizer = nil
176
+ @progress_handler = nil
177
+ @collations = {}
178
+ @functions = {}
179
+ @results_as_hash = options[:results_as_hash]
180
+ @readonly = mode & Constants::Open::READONLY != 0
133
181
  @default_transaction_mode = options[:default_transaction_mode] || :deferred
134
182
 
183
+ initialize_extensions(options[:extensions])
184
+
185
+ ForkSafety.track(self)
186
+
135
187
  if block_given?
136
188
  begin
137
189
  yield self
@@ -141,30 +193,18 @@ module SQLite3
141
193
  end
142
194
  end
143
195
 
144
- def type_translation= value # :nodoc:
145
- warn(<<-eowarn) if $VERBOSE
146
- #{caller[0]} is calling `SQLite3::Database#type_translation=` which is deprecated and will be removed in version 2.0.0.
147
- eowarn
148
- @type_translator = make_type_translator value
149
- @type_translation = value
150
- end
151
- attr_reader :type_translation # :nodoc:
152
-
153
- # Return the type translator employed by this database instance. Each
154
- # database instance has its own type translator; this allows for different
155
- # type handlers to be installed in each instance without affecting other
156
- # instances. Furthermore, the translators are instantiated lazily, so that
157
- # if a database does not use type translation, it will not be burdened by
158
- # the overhead of a useless type translator. (See the Translator class.)
159
- def translator
160
- @translator ||= Translator.new
196
+ # call-seq: db.encoding
197
+ #
198
+ # Fetch the encoding set on this database
199
+ def encoding
200
+ Encoding.find super
161
201
  end
162
202
 
163
203
  # Installs (or removes) a block that will be invoked for every access
164
204
  # to the database. If the block returns 0 (or +nil+), the statement
165
205
  # is allowed to proceed. Returning 1 causes an authorization error to
166
206
  # occur, and returning 2 causes the access to be silently denied.
167
- def authorizer( &block )
207
+ def authorizer(&block)
168
208
  self.authorizer = block
169
209
  end
170
210
 
@@ -174,7 +214,7 @@ module SQLite3
174
214
  # The Statement can then be executed using Statement#execute.
175
215
  #
176
216
  def prepare sql
177
- stmt = SQLite3::Statement.new( self, sql )
217
+ stmt = SQLite3::Statement.new(self, sql)
178
218
  return stmt unless block_given?
179
219
 
180
220
  begin
@@ -187,7 +227,7 @@ module SQLite3
187
227
  # Returns the filename for the database named +db_name+. +db_name+ defaults
188
228
  # to "main". Main return `nil` or an empty string if the database is
189
229
  # temporary or in-memory.
190
- def filename db_name = 'main'
230
+ def filename db_name = "main"
191
231
  db_filename db_name
192
232
  end
193
233
 
@@ -205,29 +245,17 @@ module SQLite3
205
245
  #
206
246
  # See also #execute2, #query, and #execute_batch for additional ways of
207
247
  # executing statements.
208
- def execute sql, bind_vars = [], *args, &block
209
- if bind_vars.nil? || !args.empty?
210
- if args.empty?
211
- bind_vars = []
212
- else
213
- bind_vars = [bind_vars] + args
214
- end
215
-
216
- warn(<<-eowarn) if $VERBOSE
217
- #{caller[0]} is calling `SQLite3::Database#execute` with nil or multiple bind params without using an array. Please switch to passing bind parameters as an array. Support for bind parameters as *args will be removed in 2.0.0.
218
- eowarn
219
- end
220
-
221
- prepare( sql ) do |stmt|
248
+ def execute sql, bind_vars = [], &block
249
+ prepare(sql) do |stmt|
222
250
  stmt.bind_params(bind_vars)
223
- stmt = ResultSet.new self, stmt
251
+ stmt = build_result_set stmt
224
252
 
225
- if block_given?
253
+ if block
226
254
  stmt.each do |row|
227
255
  yield row
228
256
  end
229
257
  else
230
- stmt.to_a
258
+ stmt.to_a.freeze
231
259
  end
232
260
  end
233
261
  end
@@ -242,15 +270,16 @@ module SQLite3
242
270
  #
243
271
  # See also #execute, #query, and #execute_batch for additional ways of
244
272
  # executing statements.
245
- def execute2( sql, *bind_vars )
246
- prepare( sql ) do |stmt|
247
- result = stmt.execute( *bind_vars )
273
+ def execute2(sql, *bind_vars)
274
+ prepare(sql) do |stmt|
275
+ result = stmt.execute(*bind_vars)
248
276
  if block_given?
249
277
  yield stmt.columns
250
278
  result.each { |row| yield row }
251
279
  else
252
- return result.inject( [ stmt.columns ] ) { |arr,row|
253
- arr << row; arr }
280
+ return result.each_with_object([stmt.columns]) { |row, arr|
281
+ arr << row
282
+ }
254
283
  end
255
284
  end
256
285
  end
@@ -261,49 +290,28 @@ module SQLite3
261
290
  # in turn. The same bind parameters, if given, will be applied to each
262
291
  # statement.
263
292
  #
264
- # This always returns +nil+, making it unsuitable for queries that return
265
- # rows.
293
+ # This always returns the result of the last statement.
266
294
  #
267
295
  # See also #execute_batch2 for additional ways of
268
296
  # executing statements.
269
- def execute_batch( sql, bind_vars = [], *args )
270
- # FIXME: remove this stuff later
271
- unless [Array, Hash].include?(bind_vars.class)
272
- bind_vars = [bind_vars]
273
- warn(<<-eowarn) if $VERBOSE
274
- #{caller[0]} is calling `SQLite3::Database#execute_batch` with bind parameters that are not a list of a hash. Please switch to passing bind parameters as an array or hash. Support for this behavior will be removed in version 2.0.0.
275
- eowarn
276
- end
277
-
278
- # FIXME: remove this stuff later
279
- if bind_vars.nil? || !args.empty?
280
- if args.empty?
281
- bind_vars = []
282
- else
283
- bind_vars = [nil] + args
284
- end
285
-
286
- warn(<<-eowarn) if $VERBOSE
287
- #{caller[0]} is calling `SQLite3::Database#execute_batch` with nil or multiple bind params without using an array. Please switch to passing bind parameters as an array. Support for this behavior will be removed in version 2.0.0.
288
- eowarn
289
- end
290
-
297
+ def execute_batch(sql, bind_vars = [])
291
298
  sql = sql.strip
292
- until sql.empty? do
293
- prepare( sql ) do |stmt|
299
+ result = nil
300
+ until sql.empty?
301
+ prepare(sql) do |stmt|
294
302
  unless stmt.closed?
295
303
  # FIXME: this should probably use sqlite3's api for batch execution
296
304
  # This implementation requires stepping over the results.
297
305
  if bind_vars.length == stmt.bind_parameter_count
298
306
  stmt.bind_params(bind_vars)
299
307
  end
300
- stmt.step
308
+ result = stmt.step
301
309
  end
302
310
  sql = stmt.remainder.strip
303
311
  end
304
312
  end
305
- # FIXME: we should not return `nil` as a success return value
306
- nil
313
+
314
+ result
307
315
  end
308
316
 
309
317
  # Executes all SQL statements in the given string. By contrast, the other
@@ -320,7 +328,7 @@ module SQLite3
320
328
  # See also #execute_batch for additional ways of
321
329
  # executing statements.
322
330
  def execute_batch2(sql, &block)
323
- if block_given?
331
+ if block
324
332
  result = exec_batch(sql, @results_as_hash)
325
333
  result.map do |val|
326
334
  yield val
@@ -341,21 +349,8 @@ module SQLite3
341
349
  # returned, or you could have problems with locks on the table. If called
342
350
  # with a block, +close+ will be invoked implicitly when the block
343
351
  # terminates.
344
- def query( sql, bind_vars = [], *args )
345
-
346
- if bind_vars.nil? || !args.empty?
347
- if args.empty?
348
- bind_vars = []
349
- else
350
- bind_vars = [bind_vars] + args
351
- end
352
-
353
- warn(<<-eowarn) if $VERBOSE
354
- #{caller[0]} is calling `SQLite3::Database#query` with nil or multiple bind params without using an array. Please switch to passing bind parameters as an array. Support for this will be removed in version 2.0.0.
355
- eowarn
356
- end
357
-
358
- result = prepare( sql ).execute( bind_vars )
352
+ def query(sql, bind_vars = [])
353
+ result = prepare(sql).execute(bind_vars)
359
354
  if block_given?
360
355
  begin
361
356
  yield result
@@ -363,7 +358,7 @@ module SQLite3
363
358
  result.close
364
359
  end
365
360
  else
366
- return result
361
+ result
367
362
  end
368
363
  end
369
364
 
@@ -371,8 +366,8 @@ module SQLite3
371
366
  # discarding all others. It is otherwise identical to #execute.
372
367
  #
373
368
  # See also #get_first_value.
374
- def get_first_row( sql, *bind_vars )
375
- execute( sql, *bind_vars ).first
369
+ def get_first_row(sql, *bind_vars)
370
+ execute(sql, *bind_vars).first
376
371
  end
377
372
 
378
373
  # A convenience method for obtaining the first value of the first row of a
@@ -380,8 +375,8 @@ module SQLite3
380
375
  # identical to #execute.
381
376
  #
382
377
  # See also #get_first_row.
383
- def get_first_value( sql, *bind_vars )
384
- query( sql, bind_vars ) do |rs|
378
+ def get_first_value(sql, *bind_vars)
379
+ query(sql, bind_vars) do |rs|
385
380
  if (row = rs.next)
386
381
  return @results_as_hash ? row[rs.columns[0]] : row[0]
387
382
  end
@@ -389,7 +384,7 @@ module SQLite3
389
384
  nil
390
385
  end
391
386
 
392
- alias :busy_timeout :busy_timeout=
387
+ alias_method :busy_timeout, :busy_timeout=
393
388
 
394
389
  # Creates a new function for use in SQL statements. It will be added as
395
390
  # +name+, with the given +arity+. (For variable arity functions, use
@@ -414,7 +409,7 @@ module SQLite3
414
409
  # end
415
410
  #
416
411
  # puts db.get_first_value( "select maim(name) from table" )
417
- def create_function name, arity, text_rep=Constants::TextRep::UTF8, &block
412
+ def create_function name, arity, text_rep = Constants::TextRep::UTF8, &block
418
413
  define_function_with_flags(name, text_rep) do |*args|
419
414
  fp = FunctionProxy.new
420
415
  block.call(fp, *args)
@@ -459,20 +454,20 @@ module SQLite3
459
454
  #
460
455
  # See also #create_aggregate_handler for a more object-oriented approach to
461
456
  # aggregate functions.
462
- def create_aggregate( name, arity, step=nil, finalize=nil,
463
- text_rep=Constants::TextRep::ANY, &block )
457
+ def create_aggregate(name, arity, step = nil, finalize = nil,
458
+ text_rep = Constants::TextRep::ANY, &block)
464
459
 
465
460
  proxy = Class.new do
466
- def self.step( &block )
461
+ def self.step(&block)
467
462
  define_method(:step_with_ctx, &block)
468
463
  end
469
464
 
470
- def self.finalize( &block )
465
+ def self.finalize(&block)
471
466
  define_method(:finalize_with_ctx, &block)
472
467
  end
473
468
  end
474
469
 
475
- if block_given?
470
+ if block
476
471
  proxy.instance_eval(&block)
477
472
  else
478
473
  proxy.class_eval do
@@ -498,7 +493,7 @@ module SQLite3
498
493
  @ctx = FunctionProxy.new
499
494
  end
500
495
 
501
- def step( *args )
496
+ def step(*args)
502
497
  step_with_ctx(@ctx, *args)
503
498
  end
504
499
 
@@ -557,7 +552,7 @@ module SQLite3
557
552
  #
558
553
  # db.create_aggregate_handler( LengthsAggregateHandler )
559
554
  # puts db.get_first_value( "select lengths(name) from A" )
560
- def create_aggregate_handler( handler )
555
+ def create_aggregate_handler(handler)
561
556
  # This is a compatibility shim so the (basically pointless) FunctionProxy
562
557
  # "ctx" object is passed as first argument to both step() and finalize().
563
558
  # Now its up to the library user whether he prefers to store his
@@ -571,7 +566,7 @@ module SQLite3
571
566
  @fp = FunctionProxy.new
572
567
  end
573
568
 
574
- def step( *args )
569
+ def step(*args)
575
570
  super(@fp, *args)
576
571
  end
577
572
 
@@ -594,7 +589,7 @@ module SQLite3
594
589
  # individual instances of the aggregate function. Regular ruby objects
595
590
  # already provide a suitable +clone+.
596
591
  # The functions arity is the arity of the +step+ method.
597
- def define_aggregator( name, aggregator )
592
+ def define_aggregator(name, aggregator)
598
593
  # Previously, this has been implemented in C. Now this is just yet
599
594
  # another compatibility shim
600
595
  proxy = Class.new do
@@ -648,9 +643,9 @@ module SQLite3
648
643
  # If a block is not given, it is the caller's responsibility to end the
649
644
  # transaction explicitly, either by calling #commit, or by calling
650
645
  # #rollback.
651
- def transaction( mode = nil )
646
+ def transaction(mode = nil)
652
647
  mode = @default_transaction_mode if mode.nil?
653
- execute "begin #{mode.to_s} transaction"
648
+ execute "begin #{mode} transaction"
654
649
 
655
650
  if block_given?
656
651
  abort = false
@@ -662,9 +657,9 @@ module SQLite3
662
657
  ensure
663
658
  abort and rollback or commit
664
659
  end
660
+ else
661
+ true
665
662
  end
666
-
667
- true
668
663
  end
669
664
 
670
665
  # Commits the current transaction. If there is no current transaction,
@@ -691,6 +686,71 @@ module SQLite3
691
686
  @readonly
692
687
  end
693
688
 
689
+ # Sets a #busy_handler that releases the GVL between retries,
690
+ # but only retries up to the indicated number of +milliseconds+.
691
+ # This is an alternative to #busy_timeout, which holds the GVL
692
+ # while SQLite sleeps and retries.
693
+ def busy_handler_timeout=(milliseconds)
694
+ timeout_seconds = milliseconds.fdiv(1000)
695
+
696
+ busy_handler do |count|
697
+ now = Process.clock_gettime(Process::CLOCK_MONOTONIC)
698
+ if count.zero?
699
+ @timeout_deadline = now + timeout_seconds
700
+ elsif now > @timeout_deadline
701
+ next false
702
+ else
703
+ sleep(0.001)
704
+ end
705
+ end
706
+ end
707
+
708
+ # call-seq:
709
+ # load_extension(extension_specifier) -> self
710
+ #
711
+ # Loads an SQLite extension library from the named file. Extension loading must be enabled using
712
+ # #enable_load_extension prior to using this method.
713
+ #
714
+ # See also: Database@SQLite+Extensions
715
+ #
716
+ # [Parameters]
717
+ # - +extension_specifier+: (String | +_ExtensionSpecifier+) If a String, it is the filesystem path
718
+ # to the sqlite extension file. If an object that responds to #to_path, the
719
+ # return value of that method is used as the filesystem path to the sqlite extension file.
720
+ #
721
+ # [Example] Using a filesystem path:
722
+ #
723
+ # db.load_extension("/path/to/my_extension.so")
724
+ #
725
+ # [Example] Using the {sqlean gem}[https://github.com/flavorjones/sqlean-ruby]:
726
+ #
727
+ # db.load_extension(SQLean::VSV)
728
+ #
729
+ def load_extension(extension_specifier)
730
+ if extension_specifier.respond_to?(:to_path)
731
+ extension_specifier = extension_specifier.to_path
732
+ elsif !extension_specifier.is_a?(String)
733
+ raise TypeError, "extension_specifier #{extension_specifier.inspect} is not a String or a valid extension specifier object"
734
+ end
735
+ load_extension_internal(extension_specifier)
736
+ end
737
+
738
+ def initialize_extensions(extensions) # :nodoc:
739
+ return if extensions.nil?
740
+ raise TypeError, "extensions must be an Array" unless extensions.is_a?(Array)
741
+ return if extensions.empty?
742
+
743
+ begin
744
+ enable_load_extension(true)
745
+
746
+ extensions.each do |extension|
747
+ load_extension(extension)
748
+ end
749
+ ensure
750
+ enable_load_extension(false)
751
+ end
752
+ end
753
+
694
754
  # A helper class for dealing with custom functions (see #create_function,
695
755
  # #create_aggregate, and #create_aggregate_handler). It encapsulates the
696
756
  # opaque function object that represents the current invocation. It also
@@ -707,54 +767,31 @@ module SQLite3
707
767
  # it is non-nil, it must quack like a Hash. If it is nil, then none of
708
768
  # the context functions will be available.
709
769
  def initialize
710
- @result = nil
711
- @context = {}
712
- end
713
-
714
- # Set the result of the function to the given error message.
715
- # The function will then return that error.
716
- def set_error( error )
717
- @driver.result_error( @func, error.to_s, -1 )
718
- end
719
-
720
- # (Only available to aggregate functions.) Returns the number of rows
721
- # that the aggregate has processed so far. This will include the current
722
- # row, and so will always return at least 1.
723
- def count
724
- @driver.aggregate_count( @func )
770
+ @result = nil
771
+ @context = {}
725
772
  end
726
773
 
727
774
  # Returns the value with the given key from the context. This is only
728
775
  # available to aggregate functions.
729
- def []( key )
730
- @context[ key ]
776
+ def [](key)
777
+ @context[key]
731
778
  end
732
779
 
733
780
  # Sets the value with the given key in the context. This is only
734
781
  # available to aggregate functions.
735
- def []=( key, value )
736
- @context[ key ] = value
782
+ def []=(key, value)
783
+ @context[key] = value
737
784
  end
738
785
  end
739
786
 
740
- # Translates a +row+ of data from the database with the given +types+
741
- def translate_from_db types, row
742
- @type_translator.call types, row
743
- end
744
-
745
- private
746
-
747
- NULL_TRANSLATOR = lambda { |_, row| row }
748
-
749
- def make_type_translator should_translate
750
- if should_translate
751
- lambda { |types, row|
752
- types.zip(row).map do |type, value|
753
- translator.translate( type, value )
754
- end
755
- }
787
+ # Given a statement, return a result set.
788
+ # This is not intended for general consumption
789
+ # :nodoc:
790
+ def build_result_set stmt
791
+ if results_as_hash
792
+ HashResultSet.new(self, stmt)
756
793
  else
757
- NULL_TRANSLATOR
794
+ ResultSet.new(self, stmt)
758
795
  end
759
796
  end
760
797
  end