sqlite3 1.5.0-arm64-darwin

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.

Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/API_CHANGES.md +49 -0
  4. data/CHANGELOG.md +425 -0
  5. data/CONTRIBUTING.md +24 -0
  6. data/ChangeLog.cvs +88 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE +27 -0
  9. data/LICENSE-DEPENDENCIES +20 -0
  10. data/README.md +233 -0
  11. data/ext/sqlite3/aggregator.c +274 -0
  12. data/ext/sqlite3/aggregator.h +12 -0
  13. data/ext/sqlite3/backup.c +168 -0
  14. data/ext/sqlite3/backup.h +15 -0
  15. data/ext/sqlite3/database.c +853 -0
  16. data/ext/sqlite3/database.h +17 -0
  17. data/ext/sqlite3/exception.c +98 -0
  18. data/ext/sqlite3/exception.h +8 -0
  19. data/ext/sqlite3/extconf.rb +252 -0
  20. data/ext/sqlite3/sqlite3.c +163 -0
  21. data/ext/sqlite3/sqlite3_ruby.h +48 -0
  22. data/ext/sqlite3/statement.c +442 -0
  23. data/ext/sqlite3/statement.h +16 -0
  24. data/faq/faq.md +431 -0
  25. data/faq/faq.rb +145 -0
  26. data/faq/faq.yml +426 -0
  27. data/lib/sqlite3/2.6/sqlite3_native.bundle +0 -0
  28. data/lib/sqlite3/2.7/sqlite3_native.bundle +0 -0
  29. data/lib/sqlite3/3.0/sqlite3_native.bundle +0 -0
  30. data/lib/sqlite3/3.1/sqlite3_native.bundle +0 -0
  31. data/lib/sqlite3/constants.rb +50 -0
  32. data/lib/sqlite3/database.rb +741 -0
  33. data/lib/sqlite3/errors.rb +35 -0
  34. data/lib/sqlite3/pragmas.rb +595 -0
  35. data/lib/sqlite3/resultset.rb +187 -0
  36. data/lib/sqlite3/statement.rb +145 -0
  37. data/lib/sqlite3/translator.rb +118 -0
  38. data/lib/sqlite3/value.rb +57 -0
  39. data/lib/sqlite3/version.rb +23 -0
  40. data/lib/sqlite3.rb +15 -0
  41. data/test/helper.rb +27 -0
  42. data/test/test_backup.rb +33 -0
  43. data/test/test_collation.rb +82 -0
  44. data/test/test_database.rb +545 -0
  45. data/test/test_database_flags.rb +95 -0
  46. data/test/test_database_readonly.rb +36 -0
  47. data/test/test_database_readwrite.rb +41 -0
  48. data/test/test_deprecated.rb +44 -0
  49. data/test/test_encoding.rb +155 -0
  50. data/test/test_integration.rb +507 -0
  51. data/test/test_integration_aggregate.rb +336 -0
  52. data/test/test_integration_open_close.rb +30 -0
  53. data/test/test_integration_pending.rb +115 -0
  54. data/test/test_integration_resultset.rb +142 -0
  55. data/test/test_integration_statement.rb +194 -0
  56. data/test/test_result_set.rb +37 -0
  57. data/test/test_sqlite3.rb +30 -0
  58. data/test/test_statement.rb +263 -0
  59. data/test/test_statement_execute.rb +35 -0
  60. metadata +190 -0
@@ -0,0 +1,741 @@
1
+ require 'sqlite3/constants'
2
+ require 'sqlite3/errors'
3
+ require 'sqlite3/pragmas'
4
+ require 'sqlite3/statement'
5
+ require 'sqlite3/translator'
6
+ require 'sqlite3/value'
7
+
8
+ module SQLite3
9
+
10
+ # The Database class encapsulates a single connection to a SQLite3 database.
11
+ # Its usage is very straightforward:
12
+ #
13
+ # require 'sqlite3'
14
+ #
15
+ # SQLite3::Database.new( "data.db" ) do |db|
16
+ # db.execute( "select * from table" ) do |row|
17
+ # p row
18
+ # end
19
+ # end
20
+ #
21
+ # It wraps the lower-level methods provides by the selected driver, and
22
+ # includes the Pragmas module for access to various pragma convenience
23
+ # methods.
24
+ #
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
29
+ # the database--insertions and updates are all still typeless.
30
+ #
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.
35
+ class Database
36
+ attr_reader :collations
37
+
38
+ include Pragmas
39
+
40
+ class << self
41
+
42
+ alias :open :new
43
+
44
+ # Quotes the given string, making it safe to use in an SQL statement.
45
+ # It replaces all instances of the single-quote character with two
46
+ # single-quote characters. The modified string is returned.
47
+ def quote( string )
48
+ string.gsub( /'/, "''" )
49
+ end
50
+
51
+ end
52
+
53
+ # A boolean that indicates whether rows in result sets should be returned
54
+ # as hashes or not. By default, rows are returned as arrays.
55
+ attr_accessor :results_as_hash
56
+
57
+ # call-seq: SQLite3::Database.new(file, options = {})
58
+ #
59
+ # Create a new Database object that opens the given file. If utf16
60
+ # is +true+, the filename is interpreted as a UTF-16 encoded string.
61
+ #
62
+ # By default, the new database will return result rows as arrays
63
+ # (#results_as_hash) and has type translation disabled (#type_translation=).
64
+
65
+ def initialize file, options = {}, zvfs = nil
66
+ mode = Constants::Open::READWRITE | Constants::Open::CREATE
67
+
68
+ file = file.to_path if file.respond_to? :to_path
69
+ if file.encoding == ::Encoding::UTF_16LE || file.encoding == ::Encoding::UTF_16BE || options[:utf16]
70
+ open16 file
71
+ else
72
+ # The three primary flag values for sqlite3_open_v2 are:
73
+ # SQLITE_OPEN_READONLY
74
+ # SQLITE_OPEN_READWRITE
75
+ # SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE -- always used for sqlite3_open and sqlite3_open16
76
+ mode = Constants::Open::READONLY if options[:readonly]
77
+
78
+ if options[:readwrite]
79
+ raise "conflicting options: readonly and readwrite" if options[:readonly]
80
+ mode = Constants::Open::READWRITE
81
+ end
82
+
83
+ if options[:flags]
84
+ if options[:readonly] || options[:readwrite]
85
+ raise "conflicting options: flags with readonly and/or readwrite"
86
+ end
87
+ mode = options[:flags]
88
+ end
89
+
90
+ open_v2 file.encode("utf-8"), mode, zvfs
91
+
92
+ if options[:strict]
93
+ disable_quirk_mode
94
+ end
95
+ end
96
+
97
+ @tracefunc = nil
98
+ @authorizer = nil
99
+ @encoding = nil
100
+ @busy_handler = nil
101
+ @collations = {}
102
+ @functions = {}
103
+ @results_as_hash = options[:results_as_hash]
104
+ @type_translation = options[:type_translation]
105
+ @type_translator = make_type_translator @type_translation
106
+ @readonly = mode & Constants::Open::READONLY != 0
107
+
108
+ if block_given?
109
+ begin
110
+ yield self
111
+ ensure
112
+ close
113
+ end
114
+ end
115
+ end
116
+
117
+ def type_translation= value # :nodoc:
118
+ warn(<<-eowarn) if $VERBOSE
119
+ #{caller[0]} is calling SQLite3::Database#type_translation=
120
+ SQLite3::Database#type_translation= is deprecated and will be removed
121
+ in version 2.0.0.
122
+ eowarn
123
+ @type_translator = make_type_translator value
124
+ @type_translation = value
125
+ end
126
+ attr_reader :type_translation # :nodoc:
127
+
128
+ # Return the type translator employed by this database instance. Each
129
+ # database instance has its own type translator; this allows for different
130
+ # type handlers to be installed in each instance without affecting other
131
+ # instances. Furthermore, the translators are instantiated lazily, so that
132
+ # if a database does not use type translation, it will not be burdened by
133
+ # the overhead of a useless type translator. (See the Translator class.)
134
+ def translator
135
+ @translator ||= Translator.new
136
+ end
137
+
138
+ # Installs (or removes) a block that will be invoked for every access
139
+ # to the database. If the block returns 0 (or +nil+), the statement
140
+ # is allowed to proceed. Returning 1 causes an authorization error to
141
+ # occur, and returning 2 causes the access to be silently denied.
142
+ def authorizer( &block )
143
+ self.authorizer = block
144
+ end
145
+
146
+ # Returns a Statement object representing the given SQL. This does not
147
+ # execute the statement; it merely prepares the statement for execution.
148
+ #
149
+ # The Statement can then be executed using Statement#execute.
150
+ #
151
+ def prepare sql
152
+ stmt = SQLite3::Statement.new( self, sql )
153
+ return stmt unless block_given?
154
+
155
+ begin
156
+ yield stmt
157
+ ensure
158
+ stmt.close unless stmt.closed?
159
+ end
160
+ end
161
+
162
+ # Returns the filename for the database named +db_name+. +db_name+ defaults
163
+ # to "main". Main return `nil` or an empty string if the database is
164
+ # temporary or in-memory.
165
+ def filename db_name = 'main'
166
+ db_filename db_name
167
+ end
168
+
169
+ # Executes the given SQL statement. If additional parameters are given,
170
+ # they are treated as bind variables, and are bound to the placeholders in
171
+ # the query.
172
+ #
173
+ # Note that if any of the values passed to this are hashes, then the
174
+ # key/value pairs are each bound separately, with the key being used as
175
+ # the name of the placeholder to bind the value to.
176
+ #
177
+ # The block is optional. If given, it will be invoked for each row returned
178
+ # by the query. Otherwise, any results are accumulated into an array and
179
+ # returned wholesale.
180
+ #
181
+ # See also #execute2, #query, and #execute_batch for additional ways of
182
+ # executing statements.
183
+ def execute sql, bind_vars = [], *args, &block
184
+ if bind_vars.nil? || !args.empty?
185
+ if args.empty?
186
+ bind_vars = []
187
+ else
188
+ bind_vars = [bind_vars] + args
189
+ end
190
+
191
+ warn(<<-eowarn) if $VERBOSE
192
+ #{caller[0]} is calling SQLite3::Database#execute with nil or multiple bind params
193
+ without using an array. Please switch to passing bind parameters as an array.
194
+ Support for bind parameters as *args will be removed in 2.0.0.
195
+ eowarn
196
+ end
197
+
198
+ prepare( sql ) do |stmt|
199
+ stmt.bind_params(bind_vars)
200
+ stmt = ResultSet.new self, stmt
201
+
202
+ if block_given?
203
+ stmt.each do |row|
204
+ yield row
205
+ end
206
+ else
207
+ stmt.to_a
208
+ end
209
+ end
210
+ end
211
+
212
+ # Executes the given SQL statement, exactly as with #execute. However, the
213
+ # first row returned (either via the block, or in the returned array) is
214
+ # always the names of the columns. Subsequent rows correspond to the data
215
+ # from the result set.
216
+ #
217
+ # Thus, even if the query itself returns no rows, this method will always
218
+ # return at least one row--the names of the columns.
219
+ #
220
+ # See also #execute, #query, and #execute_batch for additional ways of
221
+ # executing statements.
222
+ def execute2( sql, *bind_vars )
223
+ prepare( sql ) do |stmt|
224
+ result = stmt.execute( *bind_vars )
225
+ if block_given?
226
+ yield stmt.columns
227
+ result.each { |row| yield row }
228
+ else
229
+ return result.inject( [ stmt.columns ] ) { |arr,row|
230
+ arr << row; arr }
231
+ end
232
+ end
233
+ end
234
+
235
+ # Executes all SQL statements in the given string. By contrast, the other
236
+ # means of executing queries will only execute the first statement in the
237
+ # string, ignoring all subsequent statements. This will execute each one
238
+ # in turn. The same bind parameters, if given, will be applied to each
239
+ # statement.
240
+ #
241
+ # This always returns +nil+, making it unsuitable for queries that return
242
+ # rows.
243
+ #
244
+ # See also #execute_batch2 for additional ways of
245
+ # executing statements.
246
+ def execute_batch( sql, bind_vars = [], *args )
247
+ # FIXME: remove this stuff later
248
+ unless [Array, Hash].include?(bind_vars.class)
249
+ bind_vars = [bind_vars]
250
+ warn(<<-eowarn) if $VERBOSE
251
+ #{caller[0]} is calling SQLite3::Database#execute_batch with bind parameters
252
+ that are not a list of a hash. Please switch to passing bind parameters as an
253
+ array or hash. Support for this behavior will be removed in version 2.0.0.
254
+ eowarn
255
+ end
256
+
257
+ # FIXME: remove this stuff later
258
+ if bind_vars.nil? || !args.empty?
259
+ if args.empty?
260
+ bind_vars = []
261
+ else
262
+ bind_vars = [nil] + args
263
+ end
264
+
265
+ warn(<<-eowarn) if $VERBOSE
266
+ #{caller[0]} is calling SQLite3::Database#execute_batch with nil or multiple bind params
267
+ without using an array. Please switch to passing bind parameters as an array.
268
+ Support for this behavior will be removed in version 2.0.0.
269
+ eowarn
270
+ end
271
+
272
+ sql = sql.strip
273
+ until sql.empty? do
274
+ prepare( sql ) do |stmt|
275
+ unless stmt.closed?
276
+ # FIXME: this should probably use sqlite3's api for batch execution
277
+ # This implementation requires stepping over the results.
278
+ if bind_vars.length == stmt.bind_parameter_count
279
+ stmt.bind_params(bind_vars)
280
+ end
281
+ stmt.step
282
+ end
283
+ sql = stmt.remainder.strip
284
+ end
285
+ end
286
+ # FIXME: we should not return `nil` as a success return value
287
+ nil
288
+ end
289
+
290
+ # Executes all SQL statements in the given string. By contrast, the other
291
+ # means of executing queries will only execute the first statement in the
292
+ # string, ignoring all subsequent statements. This will execute each one
293
+ # in turn. Bind parameters cannot be passed to #execute_batch2.
294
+ #
295
+ # If a query is made, all values will be returned as strings.
296
+ # If no query is made, an empty array will be returned.
297
+ #
298
+ # Because all values except for 'NULL' are returned as strings,
299
+ # a block can be passed to parse the values accordingly.
300
+ #
301
+ # See also #execute_batch for additional ways of
302
+ # executing statements.
303
+ def execute_batch2(sql, &block)
304
+ if block_given?
305
+ result = exec_batch(sql, @results_as_hash)
306
+ result.map do |val|
307
+ yield val
308
+ end
309
+ else
310
+ exec_batch(sql, @results_as_hash)
311
+ end
312
+ end
313
+
314
+ # This is a convenience method for creating a statement, binding
315
+ # parameters to it, and calling execute:
316
+ #
317
+ # result = db.query( "select * from foo where a=?", [5])
318
+ # # is the same as
319
+ # result = db.prepare( "select * from foo where a=?" ).execute( 5 )
320
+ #
321
+ # You must be sure to call +close+ on the ResultSet instance that is
322
+ # returned, or you could have problems with locks on the table. If called
323
+ # with a block, +close+ will be invoked implicitly when the block
324
+ # terminates.
325
+ def query( sql, bind_vars = [], *args )
326
+
327
+ if bind_vars.nil? || !args.empty?
328
+ if args.empty?
329
+ bind_vars = []
330
+ else
331
+ bind_vars = [bind_vars] + args
332
+ end
333
+
334
+ warn(<<-eowarn) if $VERBOSE
335
+ #{caller[0]} is calling SQLite3::Database#query with nil or multiple bind params
336
+ without using an array. Please switch to passing bind parameters as an array.
337
+ Support for this will be removed in version 2.0.0.
338
+ eowarn
339
+ end
340
+
341
+ result = prepare( sql ).execute( bind_vars )
342
+ if block_given?
343
+ begin
344
+ yield result
345
+ ensure
346
+ result.close
347
+ end
348
+ else
349
+ return result
350
+ end
351
+ end
352
+
353
+ # A convenience method for obtaining the first row of a result set, and
354
+ # discarding all others. It is otherwise identical to #execute.
355
+ #
356
+ # See also #get_first_value.
357
+ def get_first_row( sql, *bind_vars )
358
+ execute( sql, *bind_vars ).first
359
+ end
360
+
361
+ # A convenience method for obtaining the first value of the first row of a
362
+ # result set, and discarding all other values and rows. It is otherwise
363
+ # identical to #execute.
364
+ #
365
+ # See also #get_first_row.
366
+ def get_first_value( sql, *bind_vars )
367
+ query( sql, bind_vars ) do |rs|
368
+ if (row = rs.next)
369
+ return @results_as_hash ? row[rs.columns[0]] : row[0]
370
+ end
371
+ end
372
+ nil
373
+ end
374
+
375
+ alias :busy_timeout :busy_timeout=
376
+
377
+ # Creates a new function for use in SQL statements. It will be added as
378
+ # +name+, with the given +arity+. (For variable arity functions, use
379
+ # -1 for the arity.)
380
+ #
381
+ # The block should accept at least one parameter--the FunctionProxy
382
+ # instance that wraps this function invocation--and any other
383
+ # arguments it needs (up to its arity).
384
+ #
385
+ # The block does not return a value directly. Instead, it will invoke
386
+ # the FunctionProxy#result= method on the +func+ parameter and
387
+ # indicate the return value that way.
388
+ #
389
+ # Example:
390
+ #
391
+ # db.create_function( "maim", 1 ) do |func, value|
392
+ # if value.nil?
393
+ # func.result = nil
394
+ # else
395
+ # func.result = value.split(//).sort.join
396
+ # end
397
+ # end
398
+ #
399
+ # puts db.get_first_value( "select maim(name) from table" )
400
+ def create_function name, arity, text_rep=Constants::TextRep::UTF8, &block
401
+ define_function_with_flags(name, text_rep) do |*args|
402
+ fp = FunctionProxy.new
403
+ block.call(fp, *args)
404
+ fp.result
405
+ end
406
+ self
407
+ end
408
+
409
+ # Creates a new aggregate function for use in SQL statements. Aggregate
410
+ # functions are functions that apply over every row in the result set,
411
+ # instead of over just a single row. (A very common aggregate function
412
+ # is the "count" function, for determining the number of rows that match
413
+ # a query.)
414
+ #
415
+ # The new function will be added as +name+, with the given +arity+. (For
416
+ # variable arity functions, use -1 for the arity.)
417
+ #
418
+ # The +step+ parameter must be a proc object that accepts as its first
419
+ # parameter a FunctionProxy instance (representing the function
420
+ # invocation), with any subsequent parameters (up to the function's arity).
421
+ # The +step+ callback will be invoked once for each row of the result set.
422
+ #
423
+ # The +finalize+ parameter must be a +proc+ object that accepts only a
424
+ # single parameter, the FunctionProxy instance representing the current
425
+ # function invocation. It should invoke FunctionProxy#result= to
426
+ # store the result of the function.
427
+ #
428
+ # Example:
429
+ #
430
+ # db.create_aggregate( "lengths", 1 ) do
431
+ # step do |func, value|
432
+ # func[ :total ] ||= 0
433
+ # func[ :total ] += ( value ? value.length : 0 )
434
+ # end
435
+ #
436
+ # finalize do |func|
437
+ # func.result = func[ :total ] || 0
438
+ # end
439
+ # end
440
+ #
441
+ # puts db.get_first_value( "select lengths(name) from table" )
442
+ #
443
+ # See also #create_aggregate_handler for a more object-oriented approach to
444
+ # aggregate functions.
445
+ def create_aggregate( name, arity, step=nil, finalize=nil,
446
+ text_rep=Constants::TextRep::ANY, &block )
447
+
448
+ proxy = Class.new do
449
+ def self.step( &block )
450
+ define_method(:step_with_ctx, &block)
451
+ end
452
+
453
+ def self.finalize( &block )
454
+ define_method(:finalize_with_ctx, &block)
455
+ end
456
+ end
457
+
458
+ if block_given?
459
+ proxy.instance_eval(&block)
460
+ else
461
+ proxy.class_eval do
462
+ define_method(:step_with_ctx, step)
463
+ define_method(:finalize_with_ctx, finalize)
464
+ end
465
+ end
466
+
467
+ proxy.class_eval do
468
+ # class instance variables
469
+ @name = name
470
+ @arity = arity
471
+
472
+ def self.name
473
+ @name
474
+ end
475
+
476
+ def self.arity
477
+ @arity
478
+ end
479
+
480
+ def initialize
481
+ @ctx = FunctionProxy.new
482
+ end
483
+
484
+ def step( *args )
485
+ step_with_ctx(@ctx, *args)
486
+ end
487
+
488
+ def finalize
489
+ finalize_with_ctx(@ctx)
490
+ @ctx.result
491
+ end
492
+ end
493
+ define_aggregator2(proxy, name)
494
+ end
495
+
496
+ # This is another approach to creating an aggregate function (see
497
+ # #create_aggregate). Instead of explicitly specifying the name,
498
+ # callbacks, arity, and type, you specify a factory object
499
+ # (the "handler") that knows how to obtain all of that information. The
500
+ # handler should respond to the following messages:
501
+ #
502
+ # +arity+:: corresponds to the +arity+ parameter of #create_aggregate. This
503
+ # message is optional, and if the handler does not respond to it,
504
+ # the function will have an arity of -1.
505
+ # +name+:: this is the name of the function. The handler _must_ implement
506
+ # this message.
507
+ # +new+:: this must be implemented by the handler. It should return a new
508
+ # instance of the object that will handle a specific invocation of
509
+ # the function.
510
+ #
511
+ # The handler instance (the object returned by the +new+ message, described
512
+ # above), must respond to the following messages:
513
+ #
514
+ # +step+:: this is the method that will be called for each step of the
515
+ # aggregate function's evaluation. It should implement the same
516
+ # signature as the +step+ callback for #create_aggregate.
517
+ # +finalize+:: this is the method that will be called to finalize the
518
+ # aggregate function's evaluation. It should implement the
519
+ # same signature as the +finalize+ callback for
520
+ # #create_aggregate.
521
+ #
522
+ # Example:
523
+ #
524
+ # class LengthsAggregateHandler
525
+ # def self.arity; 1; end
526
+ # def self.name; 'lengths'; end
527
+ #
528
+ # def initialize
529
+ # @total = 0
530
+ # end
531
+ #
532
+ # def step( ctx, name )
533
+ # @total += ( name ? name.length : 0 )
534
+ # end
535
+ #
536
+ # def finalize( ctx )
537
+ # ctx.result = @total
538
+ # end
539
+ # end
540
+ #
541
+ # db.create_aggregate_handler( LengthsAggregateHandler )
542
+ # puts db.get_first_value( "select lengths(name) from A" )
543
+ def create_aggregate_handler( handler )
544
+ # This is a compatibility shim so the (basically pointless) FunctionProxy
545
+ # "ctx" object is passed as first argument to both step() and finalize().
546
+ # Now its up to the library user whether he prefers to store his
547
+ # temporaries as instance variables or fields in the FunctionProxy.
548
+ # The library user still must set the result value with
549
+ # FunctionProxy.result= as there is no backwards compatible way to
550
+ # change this.
551
+ proxy = Class.new(handler) do
552
+ def initialize
553
+ super
554
+ @fp = FunctionProxy.new
555
+ end
556
+
557
+ def step( *args )
558
+ super(@fp, *args)
559
+ end
560
+
561
+ def finalize
562
+ super(@fp)
563
+ @fp.result
564
+ end
565
+ end
566
+ define_aggregator2(proxy, proxy.name)
567
+ self
568
+ end
569
+
570
+ # Define an aggregate function named +name+ using a object template
571
+ # object +aggregator+. +aggregator+ must respond to +step+ and +finalize+.
572
+ # +step+ will be called with row information and +finalize+ must return the
573
+ # return value for the aggregator function.
574
+ #
575
+ # _API Change:_ +aggregator+ must also implement +clone+. The provided
576
+ # +aggregator+ object will serve as template that is cloned to provide the
577
+ # individual instances of the aggregate function. Regular ruby objects
578
+ # already provide a suitable +clone+.
579
+ # The functions arity is the arity of the +step+ method.
580
+ def define_aggregator( name, aggregator )
581
+ # Previously, this has been implemented in C. Now this is just yet
582
+ # another compatibility shim
583
+ proxy = Class.new do
584
+ @template = aggregator
585
+ @name = name
586
+
587
+ def self.template
588
+ @template
589
+ end
590
+
591
+ def self.name
592
+ @name
593
+ end
594
+
595
+ def self.arity
596
+ # this is what sqlite3_obj_method_arity did before
597
+ @template.method(:step).arity
598
+ end
599
+
600
+ def initialize
601
+ @klass = self.class.template.clone
602
+ end
603
+
604
+ def step(*args)
605
+ @klass.step(*args)
606
+ end
607
+
608
+ def finalize
609
+ @klass.finalize
610
+ end
611
+ end
612
+ define_aggregator2(proxy, name)
613
+ self
614
+ end
615
+
616
+ # Begins a new transaction. Note that nested transactions are not allowed
617
+ # by SQLite, so attempting to nest a transaction will result in a runtime
618
+ # exception.
619
+ #
620
+ # The +mode+ parameter may be either <tt>:deferred</tt> (the default),
621
+ # <tt>:immediate</tt>, or <tt>:exclusive</tt>.
622
+ #
623
+ # If a block is given, the database instance is yielded to it, and the
624
+ # transaction is committed when the block terminates. If the block
625
+ # raises an exception, a rollback will be performed instead. Note that if
626
+ # a block is given, #commit and #rollback should never be called
627
+ # explicitly or you'll get an error when the block terminates.
628
+ #
629
+ # If a block is not given, it is the caller's responsibility to end the
630
+ # transaction explicitly, either by calling #commit, or by calling
631
+ # #rollback.
632
+ def transaction( mode = :deferred )
633
+ execute "begin #{mode.to_s} transaction"
634
+
635
+ if block_given?
636
+ abort = false
637
+ begin
638
+ yield self
639
+ rescue
640
+ abort = true
641
+ raise
642
+ ensure
643
+ abort and rollback or commit
644
+ end
645
+ end
646
+
647
+ true
648
+ end
649
+
650
+ # Commits the current transaction. If there is no current transaction,
651
+ # this will cause an error to be raised. This returns +true+, in order
652
+ # to allow it to be used in idioms like
653
+ # <tt>abort? and rollback or commit</tt>.
654
+ def commit
655
+ execute "commit transaction"
656
+ true
657
+ end
658
+
659
+ # Rolls the current transaction back. If there is no current transaction,
660
+ # this will cause an error to be raised. This returns +true+, in order
661
+ # to allow it to be used in idioms like
662
+ # <tt>abort? and rollback or commit</tt>.
663
+ def rollback
664
+ execute "rollback transaction"
665
+ true
666
+ end
667
+
668
+ # Returns +true+ if the database has been open in readonly mode
669
+ # A helper to check before performing any operation
670
+ def readonly?
671
+ @readonly
672
+ end
673
+
674
+ # A helper class for dealing with custom functions (see #create_function,
675
+ # #create_aggregate, and #create_aggregate_handler). It encapsulates the
676
+ # opaque function object that represents the current invocation. It also
677
+ # provides more convenient access to the API functions that operate on
678
+ # the function object.
679
+ #
680
+ # This class will almost _always_ be instantiated indirectly, by working
681
+ # with the create methods mentioned above.
682
+ class FunctionProxy
683
+ attr_accessor :result
684
+
685
+ # Create a new FunctionProxy that encapsulates the given +func+ object.
686
+ # If context is non-nil, the functions context will be set to that. If
687
+ # it is non-nil, it must quack like a Hash. If it is nil, then none of
688
+ # the context functions will be available.
689
+ def initialize
690
+ @result = nil
691
+ @context = {}
692
+ end
693
+
694
+ # Set the result of the function to the given error message.
695
+ # The function will then return that error.
696
+ def set_error( error )
697
+ @driver.result_error( @func, error.to_s, -1 )
698
+ end
699
+
700
+ # (Only available to aggregate functions.) Returns the number of rows
701
+ # that the aggregate has processed so far. This will include the current
702
+ # row, and so will always return at least 1.
703
+ def count
704
+ @driver.aggregate_count( @func )
705
+ end
706
+
707
+ # Returns the value with the given key from the context. This is only
708
+ # available to aggregate functions.
709
+ def []( key )
710
+ @context[ key ]
711
+ end
712
+
713
+ # Sets the value with the given key in the context. This is only
714
+ # available to aggregate functions.
715
+ def []=( key, value )
716
+ @context[ key ] = value
717
+ end
718
+ end
719
+
720
+ # Translates a +row+ of data from the database with the given +types+
721
+ def translate_from_db types, row
722
+ @type_translator.call types, row
723
+ end
724
+
725
+ private
726
+
727
+ NULL_TRANSLATOR = lambda { |_, row| row }
728
+
729
+ def make_type_translator should_translate
730
+ if should_translate
731
+ lambda { |types, row|
732
+ types.zip(row).map do |type, value|
733
+ translator.translate( type, value )
734
+ end
735
+ }
736
+ else
737
+ NULL_TRANSLATOR
738
+ end
739
+ end
740
+ end
741
+ end