sqlite3-ruby 1.2.5-x86-mswin32 → 1.3.0.beta.1-x86-mswin32
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.
- data/API_CHANGES.rdoc +48 -0
- data/{History.txt → CHANGELOG.rdoc} +24 -0
- data/Manifest.txt +14 -14
- data/{README.txt → README.rdoc} +1 -6
- data/Rakefile +8 -3
- data/ext/sqlite3/database.c +687 -0
- data/ext/sqlite3/database.h +15 -0
- data/ext/sqlite3/exception.c +94 -0
- data/ext/sqlite3/exception.h +8 -0
- data/ext/sqlite3/extconf.rb +26 -0
- data/ext/sqlite3/sqlite3.c +33 -0
- data/ext/sqlite3/sqlite3_ruby.h +43 -0
- data/ext/sqlite3/statement.c +412 -0
- data/ext/sqlite3/statement.h +16 -0
- data/lib/sqlite3.rb +9 -0
- data/lib/sqlite3/1.8/sqlite3_native.so +0 -0
- data/lib/sqlite3/1.9/sqlite3_native.so +0 -0
- data/lib/sqlite3/database.rb +94 -302
- data/lib/sqlite3/errors.rb +0 -24
- data/lib/sqlite3/pragmas.rb +16 -7
- data/lib/sqlite3/resultset.rb +25 -81
- data/lib/sqlite3/statement.rb +22 -107
- data/lib/sqlite3/version.rb +4 -4
- data/setup.rb +2 -2
- data/tasks/native.rake +13 -17
- data/tasks/vendor_sqlite3.rake +10 -7
- data/test/helper.rb +1 -65
- data/test/test_database.rb +239 -189
- data/test/test_encoding.rb +115 -0
- data/test/test_integration.rb +38 -35
- data/test/test_integration_open_close.rb +1 -1
- data/test/test_integration_pending.rb +6 -4
- data/test/test_integration_resultset.rb +20 -8
- data/test/test_integration_statement.rb +1 -2
- data/test/test_sqlite3.rb +9 -0
- data/test/test_statement.rb +193 -0
- metadata +84 -49
- data/ext/sqlite3_api/extconf.rb +0 -10
- data/ext/sqlite3_api/sqlite3_api.i +0 -362
- data/ext/sqlite3_api/sqlite3_api_wrap.c +0 -5018
- data/lib/1.8/sqlite3_api.so +0 -0
- data/lib/1.9/sqlite3_api.so +0 -0
- data/lib/sqlite3/driver/dl/api.rb +0 -152
- data/lib/sqlite3/driver/dl/driver.rb +0 -307
- data/lib/sqlite3/driver/native/driver.rb +0 -219
- data/tasks/benchmark.rake +0 -9
- data/tasks/gem.rake +0 -32
- data/test/bm.rb +0 -140
- data/test/driver/dl/tc_driver.rb +0 -292
- data/test/native-vs-dl.rb +0 -126
- data/test/test_errors.rb +0 -17
@@ -0,0 +1,16 @@
|
|
1
|
+
#ifndef SQLITE3_STATEMENT_RUBY
|
2
|
+
#define SQLITE3_STATEMENT_RUBY
|
3
|
+
|
4
|
+
#include <sqlite3_ruby.h>
|
5
|
+
|
6
|
+
struct _sqlite3StmtRuby {
|
7
|
+
sqlite3_stmt *st;
|
8
|
+
int done_p;
|
9
|
+
};
|
10
|
+
|
11
|
+
typedef struct _sqlite3StmtRuby sqlite3StmtRuby;
|
12
|
+
typedef sqlite3StmtRuby * sqlite3StmtRubyPtr;
|
13
|
+
|
14
|
+
void init_sqlite3_statement();
|
15
|
+
|
16
|
+
#endif
|
data/lib/sqlite3.rb
CHANGED
Binary file
|
Binary file
|
data/lib/sqlite3/database.rb
CHANGED
@@ -35,7 +35,7 @@ module SQLite3
|
|
35
35
|
class Database
|
36
36
|
include Pragmas
|
37
37
|
|
38
|
-
class <<self
|
38
|
+
class << self
|
39
39
|
|
40
40
|
alias :open :new
|
41
41
|
|
@@ -48,12 +48,6 @@ module SQLite3
|
|
48
48
|
|
49
49
|
end
|
50
50
|
|
51
|
-
# The low-level opaque database handle that this object wraps.
|
52
|
-
attr_reader :handle
|
53
|
-
|
54
|
-
# A reference to the underlying SQLite3 driver used by this database.
|
55
|
-
attr_reader :driver
|
56
|
-
|
57
51
|
# A boolean that indicates whether rows in result sets should be returned
|
58
52
|
# as hashes or not. By default, rows are returned as arrays.
|
59
53
|
attr_accessor :results_as_hash
|
@@ -62,54 +56,6 @@ module SQLite3
|
|
62
56
|
# database.
|
63
57
|
attr_accessor :type_translation
|
64
58
|
|
65
|
-
# Create a new Database object that opens the given file. If utf16
|
66
|
-
# is +true+, the filename is interpreted as a UTF-16 encoded string.
|
67
|
-
#
|
68
|
-
# By default, the new database will return result rows as arrays
|
69
|
-
# (#results_as_hash) and has type translation disabled (#type_translation=).
|
70
|
-
def initialize( file_name, options={} ) # :yields: db
|
71
|
-
utf16 = options.fetch(:utf16, false)
|
72
|
-
load_driver( options[:driver] )
|
73
|
-
|
74
|
-
@statement_factory = options[:statement_factory] || Statement
|
75
|
-
|
76
|
-
result, @handle = @driver.open( file_name, utf16 )
|
77
|
-
Error.check( result, self, "could not open database" )
|
78
|
-
|
79
|
-
@closed = false
|
80
|
-
@results_as_hash = options.fetch(:results_as_hash,false)
|
81
|
-
@type_translation = options.fetch(:type_translation,false)
|
82
|
-
@translator = nil
|
83
|
-
@transaction_active = false
|
84
|
-
|
85
|
-
if block_given?
|
86
|
-
begin
|
87
|
-
yield self
|
88
|
-
ensure
|
89
|
-
self.close
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# Return +true+ if the string is a valid (ie, parsable) SQL statement, and
|
95
|
-
# +false+ otherwise. If +utf16+ is +true+, then the string is a UTF-16
|
96
|
-
# character string.
|
97
|
-
def complete?( string, utf16=false )
|
98
|
-
@driver.complete?( string, utf16 )
|
99
|
-
end
|
100
|
-
|
101
|
-
# Return a string describing the last error to have occurred with this
|
102
|
-
# database.
|
103
|
-
def errmsg( utf16=false )
|
104
|
-
@driver.errmsg( @handle, utf16 )
|
105
|
-
end
|
106
|
-
|
107
|
-
# Return an integer representing the last error to have occurred with this
|
108
|
-
# database.
|
109
|
-
def errcode
|
110
|
-
@driver.errcode( @handle )
|
111
|
-
end
|
112
|
-
|
113
59
|
# Return the type translator employed by this database instance. Each
|
114
60
|
# database instance has its own type translator; this allows for different
|
115
61
|
# type handlers to be installed in each instance without affecting other
|
@@ -120,35 +66,12 @@ module SQLite3
|
|
120
66
|
@translator ||= Translator.new
|
121
67
|
end
|
122
68
|
|
123
|
-
# Closes this database.
|
124
|
-
def close
|
125
|
-
unless @closed
|
126
|
-
result = @driver.close( @handle )
|
127
|
-
Error.check( result, self )
|
128
|
-
end
|
129
|
-
@closed = true
|
130
|
-
end
|
131
|
-
|
132
|
-
# Returns +true+ if this database instance has been closed (see #close).
|
133
|
-
def closed?
|
134
|
-
@closed
|
135
|
-
end
|
136
|
-
|
137
|
-
# Installs (or removes) a block that will be invoked for every SQL
|
138
|
-
# statement executed. The block receives a two parameters: the +data+
|
139
|
-
# argument, and the SQL statement executed. If the block is +nil+,
|
140
|
-
# any existing tracer will be uninstalled.
|
141
|
-
def trace( data=nil, &block )
|
142
|
-
@driver.trace( @handle, data, &block )
|
143
|
-
end
|
144
|
-
|
145
69
|
# Installs (or removes) a block that will be invoked for every access
|
146
70
|
# to the database. If the block returns 0 (or +nil+), the statement
|
147
71
|
# is allowed to proceed. Returning 1 causes an authorization error to
|
148
72
|
# occur, and returning 2 causes the access to be silently denied.
|
149
|
-
def authorizer(
|
150
|
-
|
151
|
-
Error.check( result, self )
|
73
|
+
def authorizer( &block )
|
74
|
+
self.authorizer = block
|
152
75
|
end
|
153
76
|
|
154
77
|
# Returns a Statement object representing the given SQL. This does not
|
@@ -156,16 +79,14 @@ module SQLite3
|
|
156
79
|
#
|
157
80
|
# The Statement can then be executed using Statement#execute.
|
158
81
|
#
|
159
|
-
def prepare
|
160
|
-
stmt =
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
else
|
168
|
-
return stmt
|
82
|
+
def prepare sql
|
83
|
+
stmt = SQLite3::Statement.new( self, sql )
|
84
|
+
return stmt unless block_given?
|
85
|
+
|
86
|
+
begin
|
87
|
+
yield stmt
|
88
|
+
ensure
|
89
|
+
stmt.close
|
169
90
|
end
|
170
91
|
end
|
171
92
|
|
@@ -183,13 +104,38 @@ module SQLite3
|
|
183
104
|
#
|
184
105
|
# See also #execute2, #query, and #execute_batch for additional ways of
|
185
106
|
# executing statements.
|
186
|
-
def execute
|
107
|
+
def execute sql, *bind_vars, &block
|
108
|
+
# FIXME: This is a terrible hack and should be removed but is required
|
109
|
+
# for older versions of rails
|
110
|
+
hack = Object.const_defined?(:ActiveRecord) && sql =~ /^PRAGMA index_list/
|
111
|
+
|
187
112
|
prepare( sql ) do |stmt|
|
188
|
-
|
113
|
+
stmt.bind_params( *bind_vars )
|
189
114
|
if block_given?
|
190
|
-
|
115
|
+
stmt.each do |row|
|
116
|
+
if @results_as_hash
|
117
|
+
h = Hash[*stmt.columns.zip(row).flatten]
|
118
|
+
row.each_with_index { |r, i| h[i] = r }
|
119
|
+
|
120
|
+
yield h
|
121
|
+
else
|
122
|
+
yield row
|
123
|
+
end
|
124
|
+
end
|
191
125
|
else
|
192
|
-
|
126
|
+
if @results_as_hash
|
127
|
+
stmt.map { |row|
|
128
|
+
h = Hash[*stmt.columns.zip(row).flatten]
|
129
|
+
row.each_with_index { |r, i| h[i] = r }
|
130
|
+
|
131
|
+
# FIXME UGH TERRIBLE HACK!
|
132
|
+
h['unique'] = h['unique'].to_s if hack
|
133
|
+
|
134
|
+
h
|
135
|
+
}
|
136
|
+
else
|
137
|
+
stmt.to_a
|
138
|
+
end
|
193
139
|
end
|
194
140
|
end
|
195
141
|
end
|
@@ -208,10 +154,10 @@ module SQLite3
|
|
208
154
|
prepare( sql ) do |stmt|
|
209
155
|
result = stmt.execute( *bind_vars )
|
210
156
|
if block_given?
|
211
|
-
yield
|
157
|
+
yield stmt.columns
|
212
158
|
result.each { |row| yield row }
|
213
159
|
else
|
214
|
-
return result.inject( [
|
160
|
+
return result.inject( [ stmt.columns ] ) { |arr,row|
|
215
161
|
arr << row; arr }
|
216
162
|
end
|
217
163
|
end
|
@@ -229,7 +175,12 @@ module SQLite3
|
|
229
175
|
sql = sql.strip
|
230
176
|
until sql.empty? do
|
231
177
|
prepare( sql ) do |stmt|
|
232
|
-
|
178
|
+
# FIXME: this should probably use sqlite3's api for batch execution
|
179
|
+
# This implementation requires stepping over the results.
|
180
|
+
if bind_vars.length == stmt.bind_parameter_count
|
181
|
+
stmt.bind_params(bind_vars)
|
182
|
+
end
|
183
|
+
stmt.step
|
233
184
|
sql = stmt.remainder.strip
|
234
185
|
end
|
235
186
|
end
|
@@ -279,55 +230,7 @@ module SQLite3
|
|
279
230
|
nil
|
280
231
|
end
|
281
232
|
|
282
|
-
|
283
|
-
# instance.
|
284
|
-
def last_insert_row_id
|
285
|
-
@driver.last_insert_rowid( @handle )
|
286
|
-
end
|
287
|
-
|
288
|
-
# Returns the number of changes made to this database instance by the last
|
289
|
-
# operation performed. Note that a "delete from table" without a where
|
290
|
-
# clause will not affect this value.
|
291
|
-
def changes
|
292
|
-
@driver.changes( @handle )
|
293
|
-
end
|
294
|
-
|
295
|
-
# Returns the total number of changes made to this database instance
|
296
|
-
# since it was opened.
|
297
|
-
def total_changes
|
298
|
-
@driver.total_changes( @handle )
|
299
|
-
end
|
300
|
-
|
301
|
-
# Interrupts the currently executing operation, causing it to abort.
|
302
|
-
def interrupt
|
303
|
-
@driver.interrupt( @handle )
|
304
|
-
end
|
305
|
-
|
306
|
-
# Register a busy handler with this database instance. When a requested
|
307
|
-
# resource is busy, this handler will be invoked. If the handler returns
|
308
|
-
# +false+, the operation will be aborted; otherwise, the resource will
|
309
|
-
# be requested again.
|
310
|
-
#
|
311
|
-
# The handler will be invoked with the name of the resource that was
|
312
|
-
# busy, and the number of times it has been retried.
|
313
|
-
#
|
314
|
-
# See also the mutually exclusive #busy_timeout.
|
315
|
-
def busy_handler( data=nil, &block ) # :yields: data, retries
|
316
|
-
result = @driver.busy_handler( @handle, data, &block )
|
317
|
-
Error.check( result, self )
|
318
|
-
end
|
319
|
-
|
320
|
-
# Indicates that if a request for a resource terminates because that
|
321
|
-
# resource is busy, SQLite should sleep and retry for up to the indicated
|
322
|
-
# number of milliseconds. By default, SQLite does not retry
|
323
|
-
# busy resources. To restore the default behavior, send 0 as the
|
324
|
-
# +ms+ parameter.
|
325
|
-
#
|
326
|
-
# See also the mutually exclusive #busy_handler.
|
327
|
-
def busy_timeout( ms )
|
328
|
-
result = @driver.busy_timeout( @handle, ms )
|
329
|
-
Error.check( result, self )
|
330
|
-
end
|
233
|
+
alias :busy_timeout :busy_timeout=
|
331
234
|
|
332
235
|
# Creates a new function for use in SQL statements. It will be added as
|
333
236
|
# +name+, with the given +arity+. (For variable arity functions, use
|
@@ -352,23 +255,12 @@ module SQLite3
|
|
352
255
|
# end
|
353
256
|
#
|
354
257
|
# puts db.get_first_value( "select maim(name) from table" )
|
355
|
-
def create_function
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
block.call( FunctionProxy.new( @driver, func ),
|
361
|
-
*args.map{|v| Value.new(self,v)} )
|
362
|
-
rescue StandardError, Exception => e
|
363
|
-
@driver.result_error( func,
|
364
|
-
"#{e.message} (#{e.class})", -1 )
|
365
|
-
end
|
258
|
+
def create_function name, arity, text_rep=Constants::TextRep::ANY, &block
|
259
|
+
define_function(name) do |*args|
|
260
|
+
fp = FunctionProxy.new
|
261
|
+
block.call(fp, *args)
|
262
|
+
fp.result
|
366
263
|
end
|
367
|
-
|
368
|
-
result = @driver.create_function( @handle, name, arity, text_rep, nil,
|
369
|
-
callback, nil, nil )
|
370
|
-
Error.check( result, self )
|
371
|
-
|
372
264
|
self
|
373
265
|
end
|
374
266
|
|
@@ -410,47 +302,40 @@ module SQLite3
|
|
410
302
|
# aggregate functions.
|
411
303
|
def create_aggregate( name, arity, step=nil, finalize=nil,
|
412
304
|
text_rep=Constants::TextRep::ANY, &block )
|
413
|
-
# begin
|
414
|
-
if block
|
415
|
-
proxy = AggregateDefinitionProxy.new
|
416
|
-
proxy.instance_eval(&block)
|
417
|
-
step ||= proxy.step_callback
|
418
|
-
finalize ||= proxy.finalize_callback
|
419
|
-
end
|
420
305
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
ctx[:__error] = e
|
429
|
-
end
|
306
|
+
factory = Class.new do
|
307
|
+
def self.step( &block )
|
308
|
+
define_method(:step, &block)
|
309
|
+
end
|
310
|
+
|
311
|
+
def self.finalize( &block )
|
312
|
+
define_method(:finalize, &block)
|
430
313
|
end
|
431
314
|
end
|
432
315
|
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
@driver.result_error( func,
|
440
|
-
"#{e.message} (#{e.class})", -1 )
|
441
|
-
end
|
442
|
-
else
|
443
|
-
e = ctx[:__error]
|
444
|
-
@driver.result_error( func,
|
445
|
-
"#{e.message} (#{e.class})", -1 )
|
316
|
+
if block_given?
|
317
|
+
factory.instance_eval(&block)
|
318
|
+
else
|
319
|
+
factory.class_eval do
|
320
|
+
define_method(:step, step)
|
321
|
+
define_method(:finalize, finalize)
|
446
322
|
end
|
447
323
|
end
|
448
324
|
|
449
|
-
|
450
|
-
|
451
|
-
|
325
|
+
proxy = factory.new
|
326
|
+
proxy.extend(Module.new {
|
327
|
+
attr_accessor :ctx
|
452
328
|
|
453
|
-
|
329
|
+
def step( *args )
|
330
|
+
super(@ctx, *args)
|
331
|
+
end
|
332
|
+
|
333
|
+
def finalize
|
334
|
+
super(@ctx)
|
335
|
+
end
|
336
|
+
})
|
337
|
+
proxy.ctx = FunctionProxy.new
|
338
|
+
define_aggregator(name, proxy)
|
454
339
|
end
|
455
340
|
|
456
341
|
# This is another approach to creating an aggregate function (see
|
@@ -500,47 +385,22 @@ module SQLite3
|
|
500
385
|
# db.create_aggregate_handler( LengthsAggregateHandler )
|
501
386
|
# puts db.get_first_value( "select lengths(name) from A" )
|
502
387
|
def create_aggregate_handler( handler )
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
text_rep = handler.text_rep if handler.respond_to?(:text_rep)
|
508
|
-
name = handler.name
|
509
|
-
|
510
|
-
step = proc do |func,*args|
|
511
|
-
ctx = @driver.aggregate_context( func )
|
512
|
-
unless ctx[ :__error ]
|
513
|
-
ctx[ :handler ] ||= handler.new
|
514
|
-
begin
|
515
|
-
ctx[ :handler ].step( FunctionProxy.new( @driver, func, ctx ),
|
516
|
-
*args.map{|v| Value.new(self,v)} )
|
517
|
-
rescue Exception, StandardError => e
|
518
|
-
ctx[ :__error ] = e
|
519
|
-
end
|
388
|
+
proxy = Class.new do
|
389
|
+
def initialize handler
|
390
|
+
@handler = handler
|
391
|
+
@fp = FunctionProxy.new
|
520
392
|
end
|
521
|
-
end
|
522
393
|
|
523
|
-
|
524
|
-
|
525
|
-
unless ctx[ :__error ]
|
526
|
-
ctx[ :handler ] ||= handler.new
|
527
|
-
begin
|
528
|
-
ctx[ :handler ].finalize( FunctionProxy.new( @driver, func, ctx ) )
|
529
|
-
rescue Exception => e
|
530
|
-
ctx[ :__error ] = e
|
531
|
-
end
|
394
|
+
def step( *args )
|
395
|
+
@handler.step(@fp, *args)
|
532
396
|
end
|
533
397
|
|
534
|
-
|
535
|
-
|
536
|
-
@
|
398
|
+
def finalize
|
399
|
+
@handler.finalize @fp
|
400
|
+
@fp.result
|
537
401
|
end
|
538
402
|
end
|
539
|
-
|
540
|
-
result = @driver.create_function( @handle, name, arity, text_rep, nil,
|
541
|
-
nil, step, finalize )
|
542
|
-
Error.check( result, self )
|
543
|
-
|
403
|
+
define_aggregator(handler.name, proxy.new(handler.new))
|
544
404
|
self
|
545
405
|
end
|
546
406
|
|
@@ -604,33 +464,6 @@ module SQLite3
|
|
604
464
|
@transaction_active
|
605
465
|
end
|
606
466
|
|
607
|
-
# Loads the corresponding driver, or if it is nil, attempts to locate a
|
608
|
-
# suitable driver.
|
609
|
-
def load_driver( driver )
|
610
|
-
case driver
|
611
|
-
when Class
|
612
|
-
# do nothing--use what was given
|
613
|
-
when Symbol, String
|
614
|
-
require "sqlite3/driver/#{driver.to_s.downcase}/driver"
|
615
|
-
driver = SQLite3::Driver.const_get( driver )::Driver
|
616
|
-
else
|
617
|
-
[ "Native", "DL" ].each do |d|
|
618
|
-
begin
|
619
|
-
require "sqlite3/driver/#{d.downcase}/driver"
|
620
|
-
driver = SQLite3::Driver.const_get( d )::Driver
|
621
|
-
break
|
622
|
-
rescue SyntaxError
|
623
|
-
raise
|
624
|
-
rescue ScriptError, Exception, NameError
|
625
|
-
end
|
626
|
-
end
|
627
|
-
raise "no driver for sqlite3 found" unless driver
|
628
|
-
end
|
629
|
-
|
630
|
-
@driver = driver.new
|
631
|
-
end
|
632
|
-
private :load_driver
|
633
|
-
|
634
467
|
# A helper class for dealing with custom functions (see #create_function,
|
635
468
|
# #create_aggregate, and #create_aggregate_handler). It encapsulates the
|
636
469
|
# opaque function object that represents the current invocation. It also
|
@@ -640,26 +473,15 @@ module SQLite3
|
|
640
473
|
# This class will almost _always_ be instantiated indirectly, by working
|
641
474
|
# with the create methods mentioned above.
|
642
475
|
class FunctionProxy
|
476
|
+
attr_accessor :result
|
643
477
|
|
644
478
|
# Create a new FunctionProxy that encapsulates the given +func+ object.
|
645
479
|
# If context is non-nil, the functions context will be set to that. If
|
646
480
|
# it is non-nil, it must quack like a Hash. If it is nil, then none of
|
647
481
|
# the context functions will be available.
|
648
|
-
def initialize
|
649
|
-
@
|
650
|
-
@
|
651
|
-
@context = context
|
652
|
-
end
|
653
|
-
|
654
|
-
# Calls #set_result to set the result of this function.
|
655
|
-
def result=( result )
|
656
|
-
set_result( result )
|
657
|
-
end
|
658
|
-
|
659
|
-
# Set the result of the function to the given value. The function will
|
660
|
-
# then return this value.
|
661
|
-
def set_result( result, utf16=false )
|
662
|
-
@driver.result_text( @func, result, utf16 )
|
482
|
+
def initialize
|
483
|
+
@result = nil
|
484
|
+
@context = {}
|
663
485
|
end
|
664
486
|
|
665
487
|
# Set the result of the function to the given error message.
|
@@ -672,50 +494,20 @@ module SQLite3
|
|
672
494
|
# that the aggregate has processed so far. This will include the current
|
673
495
|
# row, and so will always return at least 1.
|
674
496
|
def count
|
675
|
-
ensure_aggregate!
|
676
497
|
@driver.aggregate_count( @func )
|
677
498
|
end
|
678
499
|
|
679
500
|
# Returns the value with the given key from the context. This is only
|
680
501
|
# available to aggregate functions.
|
681
502
|
def []( key )
|
682
|
-
ensure_aggregate!
|
683
503
|
@context[ key ]
|
684
504
|
end
|
685
505
|
|
686
506
|
# Sets the value with the given key in the context. This is only
|
687
507
|
# available to aggregate functions.
|
688
508
|
def []=( key, value )
|
689
|
-
ensure_aggregate!
|
690
509
|
@context[ key ] = value
|
691
510
|
end
|
692
|
-
|
693
|
-
# A function for performing a sanity check, to ensure that the function
|
694
|
-
# being invoked is an aggregate function. This is implied by the
|
695
|
-
# existence of the context variable.
|
696
|
-
def ensure_aggregate!
|
697
|
-
unless @context
|
698
|
-
raise MisuseException, "function is not an aggregate"
|
699
|
-
end
|
700
|
-
end
|
701
|
-
private :ensure_aggregate!
|
702
|
-
|
703
|
-
end
|
704
|
-
|
705
|
-
# A proxy used for defining the callbacks to an aggregate function.
|
706
|
-
class AggregateDefinitionProxy # :nodoc:
|
707
|
-
attr_reader :step_callback, :finalize_callback
|
708
|
-
|
709
|
-
def step( &block )
|
710
|
-
@step_callback = block
|
711
|
-
end
|
712
|
-
|
713
|
-
def finalize( &block )
|
714
|
-
@finalize_callback = block
|
715
|
-
end
|
716
511
|
end
|
717
|
-
|
718
512
|
end
|
719
|
-
|
720
513
|
end
|
721
|
-
|