prepare (PGconn)

    /*
     * call-seq:
     *    conn.prepare(stmt_name, sql [, param_types ] ) -> PGresult
     *
     * Prepares statement _sql_ with name _name_ to be executed later.
     * Returns a PGresult instance on success.
     * 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_prepare(int argc, VALUE *argv, VALUE self)
    {
            PGconn *conn = get_pgconn(self);
            PGresult *result = NULL;
            VALUE rb_pgresult;
            VALUE name, command, in_paramtypes;
            VALUE param;
            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 = PQprepare(conn, StringValuePtr(name), StringValuePtr(command),
                            nParams, paramTypes);

            free(paramTypes);

            rb_pgresult = new_pgresult(result);
            pgresult_check(self, rb_pgresult);
            return rb_pgresult;
    }