/*
 * call-seq:
 *    conn.send_prepare( stmt_name, sql [, param_types ] ) -> nil
 *
 * Prepares statement _sql_ with name _name_ to be executed later.
 * Sends prepare command asynchronously, and returns immediately.
 * On failure, it raises a PGError exception.
 *
 * +param_types+ is an optional parameter to specify the Oids of the 
 * types of the parameters.
 *
 * If the types are not specified, they will be inferred by PostgreSQL.
 * Instead of specifying type oids, it's recommended to simply add
 * explicit casts in the query to ensure that the right type is used.
 *
 * For example: "SELECT $1::int"
 * 
 * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
 * inside the SQL query.
 */
static VALUE
pgconn_send_prepare(argc, argv, self)
    int argc;
        VALUE *argv;
        VALUE self;
{
    PGconn *conn = get_pgconn(self);
        int result;
        VALUE name, command, in_paramtypes;
        VALUE param;
        VALUE error;
        int i = 0;
        int nParams = 0;
        Oid *paramTypes = NULL;

    rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
        Check_Type(name, T_STRING);
    Check_Type(command, T_STRING);

        if(! NIL_P(in_paramtypes)) {
                Check_Type(in_paramtypes, T_ARRAY);
                nParams = RARRAY(in_paramtypes)->len;
                paramTypes = ALLOC_N(Oid, nParams); 
                for(i = 0; i < nParams; i++) {
                        param = rb_ary_entry(in_paramtypes, i);
                        Check_Type(param, T_FIXNUM);
                        if(param == Qnil)
                                paramTypes[i] = 0;
                        else
                                paramTypes[i] = NUM2INT(param);
                }
        }
        result = PQsendPrepare(conn, StringValuePtr(name), StringValuePtr(command),
                        nParams, paramTypes);

        free(paramTypes);

        if(result == 0) {
                error = rb_exc_new2(rb_ePGError, PQerrorMessage(conn));
                rb_iv_set(error, "@connection", self);
                rb_exc_raise(error);
        }
        return Qnil;
}