/** * call-seq: * create_aggregate( db, name, args, step, finalize ) -> nil * * Defines a new aggregate function that may be invoked from within an SQL * statement. The +args+ parameter specifies how many arguments the function * expects--use -1 to specify variable arity. * * The +step+ parameter specifies a proc object that will be invoked for each * row that the function processes. It should accept an opaque handle to the * function object, followed by its expected arguments: * * step = proc do |func, *args| * ... * end * * The +finalize+ parameter specifies a proc object that will be invoked after * all rows have been processed. This gives the function an opportunity to * aggregate and finalize the results. It should accept a single parameter: * the opaque function handle: * * finalize = proc do |func| * ... * end * * The function object is used when calling the #set_result, * #set_result_error, #aggregate_context, and #aggregate_count methods. */ static VALUE static_api_create_aggregate( VALUE module, VALUE db, VALUE name, VALUE n, VALUE step, VALUE finalize ) { sqlite *handle; int result; VALUE data; GetDB( handle, db ); Check_Type( name, T_STRING ); Check_Type( n, T_FIXNUM ); if( !rb_obj_is_kind_of( step, rb_cProc ) ) { rb_raise( rb_eArgError, "step must be a proc" ); } if( !rb_obj_is_kind_of( finalize, rb_cProc ) ) { rb_raise( rb_eArgError, "finalize must be a proc" ); } /* FIXME: will the GC kill this before it is used? */ data = rb_ary_new3( 2, step, finalize ); result = sqlite_create_aggregate( handle, StringValueCStr(name), FIX2INT(n), static_function_callback, static_aggregate_finalize_callback, (void*)data ); if( result != SQLITE_OK ) { static_raise_db_error( result, "create aggregate %s(%d)", StringValueCStr(name), FIX2INT(n) ); /* "raise" does not return */ } return Qnil; }