/**
 * 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;
}