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