Method: SQLite::Database#create_aggregate
- Defined in:
- lib/sqlite/database.rb
#create_aggregate(name, arity, step, finalize, type = nil) ⇒ Object
Creates a new aggregate function for use in SQL statements. Aggregate functions are functions that apply over every row in the result set, instead of over just a single row. (A very common aggregate function is the “count” function, for determining the number of rows that match a query.)
The new function will be added as name
, with the given arity
. (For variable arity functions, use -1 for the arity.) If type
is non-nil, it should be a value as described in #create_function.
The step
parameter must be a proc object that accepts as its first parameter a FunctionProxy instance (representing the function invocation), with any subsequent parameters (up to the function’s arity). The step
callback will be invoked once for each row of the result set.
The finalize
parameter must be a proc
object that accepts only a single parameter, the FunctionProxy instance representing the current function invocation. It should invoke FunctionProxy#set_result to store the result of the function.
Example:
step = proc do |func, value|
func[ :total ] ||= 0
func[ :total ] += ( value ? value.length : 0 )
end
finalize = proc do |func|
func.set_result( func[ :total ] || 0 )
end
db.create_aggregate( "lengths", 1, step, finalize, :numeric )
puts db.get_first_value( "select lengths(name) from table" )
See also #create_aggregate_handler for a more object-oriented approach to aggregate functions.
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 |
# File 'lib/sqlite/database.rb', line 411 def create_aggregate( name, arity, step, finalize, type=nil ) case type when :numeric type = SQLite::API::NUMERIC when :text type = SQLite::API::TEXT when :args type = SQLite::API::ARGS end step_callback = proc do |func,*args| ctx = SQLite::API.aggregate_context( func ) unless ctx[:__error] begin step.call( FunctionProxy.new( func, ctx ), *args ) rescue Exception => e ctx[:__error] = e end end end finalize_callback = proc do |func| ctx = SQLite::API.aggregate_context( func ) unless ctx[:__error] begin finalize.call( FunctionProxy.new( func, ctx ) ) rescue Exception => e SQLite::API.set_result_error( func, "#{e.} (#{e.class})" ) end else e = ctx[:__error] SQLite::API.set_result_error( func, "#{e.} (#{e.class})" ) end end SQLite::API.create_aggregate( @handle, name, arity, step_callback, finalize_callback ) SQLite::API.function_type( @handle, name, type ) if type self end |