sqlite-ruby 2.1.0-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,34 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # * The names of its contributors may not be used to endorse or promote
17
+ # products derived from this software without specific prior written
18
+ # permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # =============================================================================
31
+ #++
32
+
33
+ require 'sqlite/database'
34
+ require 'sqlite/version'
@@ -0,0 +1,682 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions are met:
8
+ #
9
+ # * Redistributions of source code must retain the above copyright notice,
10
+ # this list of conditions and the following disclaimer.
11
+ #
12
+ # * Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the distribution.
15
+ #
16
+ # * The names of its contributors may not be used to endorse or promote
17
+ # products derived from this software without specific prior written
18
+ # permission.
19
+ #
20
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
24
+ # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ # =============================================================================
31
+ #++
32
+
33
+ require 'base64'
34
+ require 'sqlite_api'
35
+ require 'sqlite/pragmas'
36
+ require 'sqlite/statement'
37
+ require 'sqlite/translator'
38
+
39
+ module SQLite
40
+
41
+ # The Database class encapsulates a single connection to a SQLite database.
42
+ # Its usage is very straightforward:
43
+ #
44
+ # require 'sqlite'
45
+ #
46
+ # db = SQLite::Database.new( "data.db" )
47
+ #
48
+ # db.execute( "select * from table" ) do |row|
49
+ # p row
50
+ # end
51
+ #
52
+ # db.close
53
+ #
54
+ # It wraps the lower-level methods provides by the API module, include
55
+ # includes the Pragmas module for access to various pragma convenience
56
+ # methods.
57
+ #
58
+ # The Database class provides type translation services as well, by which
59
+ # the SQLite data types (which are all represented as strings) may be
60
+ # converted into their corresponding types (as defined in the schemas
61
+ # for their tables). This translation only occurs when querying data from
62
+ # the database--insertions and updates are all still typeless.
63
+ #
64
+ # Furthermore, the Database class has been designed to work well with the
65
+ # ArrayFields module from Ara Howard. If you require the ArrayFields
66
+ # module before performing a query, and if you have not enabled results as
67
+ # hashes, then the results will all be indexible by field name.
68
+ class Database
69
+ include SQLite::Pragmas
70
+
71
+ # Opens the database contained in the given file. This just calls #new,
72
+ # passing 0 as the mode parameter. This returns the new Database
73
+ # instance.
74
+ def self.open( file_name )
75
+ new( file_name, 0 )
76
+ end
77
+
78
+ # Quotes the given string, making it safe to use in an SQL statement.
79
+ # It replaces all instances of the single-quote character with two
80
+ # single-quote characters. The modified string is returned.
81
+ def self.quote( string )
82
+ string.gsub( /'/, "''" )
83
+ end
84
+
85
+ # Returns a string that represents the serialization of the given object.
86
+ # The string may safely be used in an SQL statement.
87
+ def self.encode( object )
88
+ Base64.encode64( Marshal.dump( object ) ).strip
89
+ end
90
+
91
+ # Unserializes the object contained in the given string. The string must be
92
+ # one that was returned by #encode.
93
+ def self.decode( string )
94
+ Marshal.load( Base64.decode64( string ) )
95
+ end
96
+
97
+ # Return +true+ if the string is a valid (ie, parsable) SQL statement, and
98
+ # +false+ otherwise.
99
+ def self.complete?( string )
100
+ SQLite::API.complete( string )
101
+ end
102
+
103
+ # The low-level opaque database handle that this object wraps.
104
+ attr_reader :handle
105
+
106
+ # A boolean that indicates whether rows in result sets should be returned
107
+ # as hashes or not. By default, rows are returned as arrays.
108
+ attr_accessor :results_as_hash
109
+
110
+ # Create a new Database object that opens the given file. The mode
111
+ # parameter has no meaning yet, and may be omitted. If the file does not
112
+ # exist, it will be created if possible.
113
+ #
114
+ # By default, the new database will return result rows as arrays
115
+ # (#results_as_hash) and has type translation disabled (#type_translation=).
116
+ def initialize( file_name, mode=0 )
117
+ @handle = SQLite::API.open( file_name, mode )
118
+ @closed = false
119
+ @results_as_hash = false
120
+ @type_translation = false
121
+ @translator = nil
122
+ end
123
+
124
+ # Return the type translator employed by this database instance. Each
125
+ # database instance has its own type translator; this allows for different
126
+ # type handlers to be installed in each instance without affecting other
127
+ # instances. Furthermore, the translators are instantiated lazily, so that
128
+ # if a database does not use type translation, it will not be burdened by
129
+ # the overhead of a useless type translator. (See the Translator class.)
130
+ def translator
131
+ @translator ||= Translator.new
132
+ end
133
+
134
+ # Returns +true+ if type translation is enabled for this database, or
135
+ # +false+ otherwise.
136
+ def type_translation
137
+ @type_translation
138
+ end
139
+
140
+ # Enable or disable type translation for this database.
141
+ def type_translation=( mode )
142
+ @type_translation = mode
143
+ end
144
+
145
+ # Closes this database. No checks are done to ensure that a database is not
146
+ # closed more than once, and closing a database more than once can be
147
+ # catastrophic.
148
+ def close
149
+ SQLite::API.close( @handle )
150
+ @closed = true
151
+ end
152
+
153
+ # Returns +true+ if this database instance has been closed (see #close).
154
+ def closed?
155
+ @closed
156
+ end
157
+
158
+ # Returns a Statement object representing the given SQL. This does not
159
+ # execute the statement; it merely prepares the statement for execution.
160
+ def prepare( sql )
161
+ Statement.new( self, sql )
162
+ end
163
+
164
+ # Executes the given SQL statement. If additional parameters are given,
165
+ # they are treated as bind variables, and are bound to the placeholders in
166
+ # the query.
167
+ #
168
+ # Each placeholder must match one of the following formats:
169
+ #
170
+ # * <tt>?</tt>
171
+ # * <tt>?nnn</tt>
172
+ # * <tt>:word</tt>
173
+ # * <tt>:word:</tt>
174
+ #
175
+ # where _nnn_ is an integer value indicating the index of the bind
176
+ # variable to be bound at that position, and _word_ is an alphanumeric
177
+ # identifier for that placeholder. For "<tt>?</tt>", an index is
178
+ # automatically assigned of one greater than the previous index used
179
+ # (or 1, if it is the first).
180
+ #
181
+ # Note that if any of the values passed to this are hashes, then the
182
+ # key/value pairs are each bound separately, with the key being used as
183
+ # the name of the placeholder to bind the value to.
184
+ #
185
+ # The block is optional. If given, it will be invoked for each row returned
186
+ # by the query. Otherwise, any results are accumulated into an array and
187
+ # returned wholesale.
188
+ #
189
+ # See also #execute2, #execute_batch and #query for additional ways of
190
+ # executing statements.
191
+ def execute( sql, *bind_vars )
192
+ stmt = prepare( sql )
193
+ stmt.bind_params( *bind_vars )
194
+ result = stmt.execute
195
+ begin
196
+ if block_given?
197
+ result.each { |row| yield row }
198
+ else
199
+ return result.inject( [] ) { |arr,row| arr << row; arr }
200
+ end
201
+ ensure
202
+ result.close
203
+ end
204
+ end
205
+
206
+ # Executes the given SQL statement, exactly as with #execute. However, the
207
+ # first row returned (either via the block, or in the returned array) is
208
+ # always the names of the columns. Subsequent rows correspond to the data
209
+ # from the result set.
210
+ #
211
+ # Thus, even if the query itself returns no rows, this method will always
212
+ # return at least one row--the names of the columns.
213
+ #
214
+ # See also #execute, #execute_batch and #query for additional ways of
215
+ # executing statements.
216
+ def execute2( sql, *bind_vars )
217
+ stmt = prepare( sql )
218
+ stmt.bind_params( *bind_vars )
219
+ result = stmt.execute
220
+ begin
221
+ if block_given?
222
+ yield result.columns
223
+ result.each { |row| yield row }
224
+ else
225
+ return result.inject( [ result.columns ] ) { |arr,row| arr << row; arr }
226
+ end
227
+ ensure
228
+ result.close
229
+ end
230
+ end
231
+
232
+ # Executes all SQL statements in the given string. By contrast, the other
233
+ # means of executing queries will only execute the first statement in the
234
+ # string, ignoring all subsequent statements. This will execute each one
235
+ # in turn. The same bind parameters, if given, will be applied to each
236
+ # statement.
237
+ #
238
+ # This always returns +nil+, making it unsuitable for queries that return
239
+ # rows.
240
+ def execute_batch( sql, *bind_vars )
241
+ loop do
242
+ stmt = prepare( sql )
243
+ stmt.bind_params *bind_vars
244
+ stmt.execute
245
+ sql = stmt.remainder
246
+ break if sql.length < 1
247
+ end
248
+ nil
249
+ end
250
+
251
+ # This does like #execute and #execute2 (binding variables and so forth),
252
+ # but instead of yielding each row from the result set, this will yield the
253
+ # ResultSet instance itself (q.v.). If no block is given, the ResultSet
254
+ # instance will be returned.
255
+ def query( sql, *bind_vars, &block ) # :yields: result_set
256
+ stmt = prepare( sql )
257
+ stmt.bind_params( *bind_vars )
258
+ stmt.execute( &block )
259
+ end
260
+
261
+ # A convenience method for obtaining the first row of a result set, and
262
+ # discarding all others. It is otherwise identical to #execute.
263
+ #
264
+ # See also #get_first_value.
265
+ def get_first_row( sql, *bind_vars )
266
+ execute( sql, *bind_vars ) { |row| return row }
267
+ nil
268
+ end
269
+
270
+ # A convenience method for obtaining the first value of the first row of a
271
+ # result set, and discarding all other values and rows. It is otherwise
272
+ # identical to #execute.
273
+ #
274
+ # See also #get_first_row.
275
+ def get_first_value( sql, *bind_vars )
276
+ execute( sql, *bind_vars ) { |row| return row[0] }
277
+ nil
278
+ end
279
+
280
+ # Obtains the unique row ID of the last row to be inserted by this Database
281
+ # instance.
282
+ def last_insert_row_id
283
+ SQLite::API.last_insert_row_id( @handle )
284
+ end
285
+
286
+ # Returns the number of changes made to this database instance by the last
287
+ # operation performed. Note that a "delete from table" without a where
288
+ # clause will not affect this value.
289
+ def changes
290
+ SQLite::API.changes( @handle )
291
+ end
292
+
293
+ # Interrupts the currently executing operation, causing it to abort.
294
+ def interrupt
295
+ SQLite::API.interrupt( @handle )
296
+ end
297
+
298
+ # Register a busy handler with this database instance. When a requested
299
+ # resource is busy, this handler will be invoked. If the handler returns
300
+ # +false+, the operation will be aborted; otherwise, the resource will
301
+ # be requested again.
302
+ #
303
+ # The handler will be invoked with the name of the resource that was
304
+ # busy, and the number of times it has been retried.
305
+ #
306
+ # See also #busy_timeout.
307
+ def busy_handler( &block ) # :yields: resource, retries
308
+ SQLite::API.busy_handler( @handle, block )
309
+ end
310
+
311
+ # Indicates that if a request for a resource terminates because that
312
+ # resource is busy, SQLite should wait for the indicated number of
313
+ # milliseconds before trying again. By default, SQLite does not retry
314
+ # busy resources. To restore the default behavior, send 0 as the
315
+ # +ms+ parameter.
316
+ #
317
+ # See also #busy_handler.
318
+ def busy_timeout( ms )
319
+ SQLite::API.busy_timeout( @handle, ms )
320
+ end
321
+
322
+ # Creates a new function for use in SQL statements. It will be added as
323
+ # +name+, with the given +arity+. (For variable arity functions, use
324
+ # -1 for the arity.) If +type+ is non-nil, it should either be an
325
+ # integer (indicating that the type of the function is always the
326
+ # type of the argument at that index), or one of the symbols
327
+ # <tt>:numeric</tt>, <tt>:text</tt>, <tt>:args</tt> (in which case
328
+ # the function is, respectively, numeric, textual, or the same type as
329
+ # its arguments).
330
+ #
331
+ # The block should accept at least one parameter--the FunctionProxy
332
+ # instance that wraps this function invocation--and any other
333
+ # arguments it needs (up to its arity).
334
+ #
335
+ # The block does not return a value directly. Instead, it will invoke
336
+ # the FunctionProxy#set_result method on the +func+ parameter and
337
+ # indicate the return value that way.
338
+ #
339
+ # Example:
340
+ #
341
+ # db.create_function( "maim", 1, :text ) do |func, value|
342
+ # if value.nil?
343
+ # func.set_value nil
344
+ # else
345
+ # func.set_value value.split(//).sort.join
346
+ # end
347
+ # end
348
+ #
349
+ # puts db.get_first_value( "select maim(name) from table" )
350
+ def create_function( name, arity, type=nil, &block ) # :yields: func, *args
351
+ case type
352
+ when :numeric
353
+ type = SQLite::API::NUMERIC
354
+ when :text
355
+ type = SQLite::API::TEXT
356
+ when :args
357
+ type = SQLite::API::ARGS
358
+ end
359
+
360
+ callback = proc do |func,*args|
361
+ begin
362
+ block.call( FunctionProxy.new( func ), *args )
363
+ rescue Exception => e
364
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
365
+ end
366
+ end
367
+
368
+ SQLite::API.create_function( @handle, name, arity, callback )
369
+ SQLite::API.function_type( @handle, name, type ) if type
370
+
371
+ self
372
+ end
373
+
374
+ # Creates a new aggregate function for use in SQL statements. Aggregate
375
+ # functions are functions that apply over every row in the result set,
376
+ # instead of over just a single row. (A very common aggregate function
377
+ # is the "count" function, for determining the number of rows that match
378
+ # a query.)
379
+ #
380
+ # The new function will be added as +name+, with the given +arity+. (For
381
+ # variable arity functions, use -1 for the arity.) If +type+ is non-nil,
382
+ # it should be a value as described in #create_function.
383
+ #
384
+ # The +step+ parameter must be a proc object that accepts as its first
385
+ # parameter a FunctionProxy instance (representing the function
386
+ # invocation), with any subsequent parameters (up to the function's arity).
387
+ # The +step+ callback will be invoked once for each row of the result set.
388
+ #
389
+ # The +finalize+ parameter must be a +proc+ object that accepts only a
390
+ # single parameter, the FunctionProxy instance representing the current
391
+ # function invocation. It should invoke FunctionProxy#set_result to
392
+ # store the result of the function.
393
+ #
394
+ # Example:
395
+ #
396
+ # step = proc do |func, value|
397
+ # func[ :total ] ||= 0
398
+ # func[ :total ] += ( value ? value.length : 0 )
399
+ # end
400
+ #
401
+ # finalize = proc do |func|
402
+ # func.set_result( func[ :total ] || 0 )
403
+ # end
404
+ #
405
+ # db.create_aggregate( "lengths", 1, step, finalize, :numeric )
406
+ #
407
+ # puts db.get_first_value( "select lengths(name) from table" )
408
+ #
409
+ # See also #create_aggregate_handler for a more object-oriented approach to
410
+ # aggregate functions.
411
+ def create_aggregate( name, arity, step, finalize, type=nil )
412
+ case type
413
+ when :numeric
414
+ type = SQLite::API::NUMERIC
415
+ when :text
416
+ type = SQLite::API::TEXT
417
+ when :args
418
+ type = SQLite::API::ARGS
419
+ end
420
+
421
+ step_callback = proc do |func,*args|
422
+ ctx = SQLite::API.aggregate_context( func )
423
+ unless ctx[:__error]
424
+ begin
425
+ step.call( FunctionProxy.new( func, ctx ), *args )
426
+ rescue Exception => e
427
+ ctx[:__error] = e
428
+ end
429
+ end
430
+ end
431
+
432
+ finalize_callback = proc do |func|
433
+ ctx = SQLite::API.aggregate_context( func )
434
+ unless ctx[:__error]
435
+ begin
436
+ finalize.call( FunctionProxy.new( func, ctx ) )
437
+ rescue Exception => e
438
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
439
+ end
440
+ else
441
+ e = ctx[:__error]
442
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
443
+ end
444
+ end
445
+
446
+ SQLite::API.create_aggregate( @handle, name, arity,
447
+ step_callback, finalize_callback )
448
+
449
+ SQLite::API.function_type( @handle, name, type ) if type
450
+
451
+ self
452
+ end
453
+
454
+ # This is another approach to creating an aggregate function (see
455
+ # #create_aggregate). Instead of explicitly specifying the name,
456
+ # callbacks, arity, and type, you specify a factory object
457
+ # (the "handler") that knows how to obtain all of that information. The
458
+ # handler should respond to the following messages:
459
+ #
460
+ # +function_type+:: corresponds to the +type+ parameter of
461
+ # #create_aggregate. This is an optional message, and if
462
+ # the handler does not respond to it, the function type
463
+ # will not be set for this function.
464
+ # +arity+:: corresponds to the +arity+ parameter of #create_aggregate. This
465
+ # message is optional, and if the handler does not respond to it,
466
+ # the function will have an arity of -1.
467
+ # +name+:: this is the name of the function. The handler _must_ implement
468
+ # this message.
469
+ # +new+:: this must be implemented by the handler. It should return a new
470
+ # instance of the object that will handle a specific invocation of
471
+ # the function.
472
+ #
473
+ # The handler instance (the object returned by the +new+ message, described
474
+ # above), must respond to the following messages:
475
+ #
476
+ # +step+:: this is the method that will be called for each step of the
477
+ # aggregate function's evaluation. It should implement the same
478
+ # signature as the +step+ callback for #create_aggregate.
479
+ # +finalize+:: this is the method that will be called to finalize the
480
+ # aggregate function's evaluation. It should implement the
481
+ # same signature as the +finalize+ callback for
482
+ # #create_aggregate.
483
+ #
484
+ # Example:
485
+ #
486
+ # class LengthsAggregateHandler
487
+ # def self.function_type; :numeric; end
488
+ # def self.arity; 1; end
489
+ #
490
+ # def initialize
491
+ # @total = 0
492
+ # end
493
+ #
494
+ # def step( ctx, name )
495
+ # @total += ( name ? name.length : 0 )
496
+ # end
497
+ #
498
+ # def finalize( ctx )
499
+ # ctx.set_result( @total )
500
+ # end
501
+ # end
502
+ #
503
+ # db.create_aggregate_handler( LengthsAggregateHandler )
504
+ # puts db.get_first_value( "select lengths(name) from A" )
505
+ def create_aggregate_handler( handler )
506
+ type = nil
507
+ arity = -1
508
+
509
+ type = handler.function_type if handler.respond_to?(:function_type)
510
+ arity = handler.arity if handler.respond_to?(:arity)
511
+ name = handler.name
512
+
513
+ case type
514
+ when :numeric
515
+ type = SQLite::API::NUMERIC
516
+ when :text
517
+ type = SQLite::API::TEXT
518
+ when :args
519
+ type = SQLite::API::ARGS
520
+ end
521
+
522
+ step = proc do |func,*args|
523
+ ctx = SQLite::API.aggregate_context( func )
524
+ unless ctx[ :__error ]
525
+ ctx[ :handler ] ||= handler.new
526
+ begin
527
+ ctx[ :handler ].step( FunctionProxy.new( func, ctx ), *args )
528
+ rescue Exception => e
529
+ ctx[ :__error ] = e
530
+ end
531
+ end
532
+ end
533
+
534
+ finalize = proc do |func|
535
+ ctx = SQLite::API.aggregate_context( func )
536
+ unless ctx[ :__error ]
537
+ ctx[ :handler ] ||= handler.new
538
+ begin
539
+ ctx[ :handler ].finalize( FunctionProxy.new( func, ctx ) )
540
+ rescue Exception => e
541
+ ctx[ :__error ] = e
542
+ end
543
+ end
544
+
545
+ if ctx[ :__error ]
546
+ e = ctx[ :__error ]
547
+ SQLite::API.set_result_error( func, "#{e.message} (#{e.class})" )
548
+ end
549
+ end
550
+
551
+ SQLite::API.create_aggregate( @handle, name, arity, step, finalize )
552
+ SQLite::API.function_type( @handle, name, type ) if type
553
+
554
+ self
555
+ end
556
+
557
+ # Begins a new transaction. Note that nested transactions are not allowed
558
+ # by SQLite, so attempting to nest a transaction will result in a runtime
559
+ # exception.
560
+ #
561
+ # If a block is given, the database instance is yielded to it, and the
562
+ # transaction is committed when the block terminates. If the block
563
+ # raises an exception, a rollback will be performed instead. Note that if
564
+ # a block is given, #commit and #rollback should never be called
565
+ # explicitly or you'll get an error when the block terminates.
566
+ #
567
+ # If a block is not given, it is the caller's responsibility to end the
568
+ # transaction explicitly, either by calling #commit, or by calling
569
+ # #rollback.
570
+ def transaction
571
+ execute "begin transaction"
572
+ @transaction_active = true
573
+
574
+ if block_given?
575
+ abort = false
576
+ begin
577
+ yield self
578
+ rescue Exception
579
+ abort = true
580
+ raise
581
+ ensure
582
+ abort and rollback or commit
583
+ end
584
+ end
585
+
586
+ true
587
+ end
588
+
589
+ # Commits the current transaction. If there is no current transaction,
590
+ # this will cause an error to be raised. This returns +true+, in order
591
+ # to allow it to be used in idioms like
592
+ # <tt>abort? and rollback or commit</tt>.
593
+ def commit
594
+ execute "commit transaction"
595
+ @transaction_active = false
596
+ true
597
+ end
598
+
599
+ # Rolls the current transaction back. If there is no current transaction,
600
+ # this will cause an error to be raised. This returns +true+, in order
601
+ # to allow it to be used in idioms like
602
+ # <tt>abort? and rollback or commit</tt>.
603
+ def rollback
604
+ execute "rollback transaction"
605
+ @transaction_active = false
606
+ true
607
+ end
608
+
609
+ # Returns +true+ if there is a transaction active, and +false+ otherwise.
610
+ def transaction_active?
611
+ @transaction_active
612
+ end
613
+
614
+ # A helper class for dealing with custom functions (see #create_function,
615
+ # #create_aggregate, and #create_aggregate_handler). It encapsulates the
616
+ # opaque function object that represents the current invocation. It also
617
+ # provides more convenient access to the API functions that operate on
618
+ # the function object.
619
+ #
620
+ # This class will almost _always_ be instantiated indirectly, by working
621
+ # with the create methods mentioned above.
622
+ class FunctionProxy
623
+
624
+ # Create a new FunctionProxy that encapsulates the given +func+ object.
625
+ # If context is non-nil, the functions context will be set to that. If
626
+ # it is non-nil, it must quack like a Hash. If it is nil, then none of
627
+ # the context functions will be available.
628
+ def initialize( func, context=nil )
629
+ @func = func
630
+ @context = context
631
+ end
632
+
633
+ # Set the result of the function to the given value. The function will
634
+ # then return this value.
635
+ def set_result( result )
636
+ SQLite::API.set_result( @func, result )
637
+ end
638
+
639
+ # Set the result of the function to the given error message, which must
640
+ # be a string. The function will then return that error.
641
+ def set_error( error )
642
+ SQLite::API.set_result_error( @func, error )
643
+ end
644
+
645
+ # (Only available to aggregate functions.) Returns the number of rows
646
+ # that the aggregate has processed so far. This will include the current
647
+ # row, and so will always return at least 1.
648
+ def count
649
+ ensure_aggregate!
650
+ SQLite::API.aggregate_count( @func )
651
+ end
652
+
653
+ # Returns the value with the given key from the context. This is only
654
+ # available to aggregate functions.
655
+ def []( key )
656
+ ensure_aggregate!
657
+ @context[ key ]
658
+ end
659
+
660
+ # Sets the value with the given key in the context. This is only
661
+ # available to aggregate functions.
662
+ def []=( key, value )
663
+ ensure_aggregate!
664
+ @context[ key ] = value
665
+ end
666
+
667
+ # A function for performing a sanity check, to ensure that the function
668
+ # being invoked is an aggregate function. This is implied by the
669
+ # existence of the context variable.
670
+ def ensure_aggregate!
671
+ unless @context
672
+ raise Exceptions::MisuseException, "function is not an aggregate"
673
+ end
674
+ end
675
+ private :ensure_aggregate!
676
+
677
+ end
678
+
679
+ end
680
+
681
+ end
682
+