/*
* call-seq:
* conn.exec_prepared(statement_name [, params, result_format ] ) -> PGresult
*
* Execute prepared named statement specified by _statement_name_.
* Returns a PGresult instance on success.
* On failure, it raises a PGError exception.
*
* +params+ is an array of the optional bind parameters for the
* SQL query. Each element of the +params+ array may be either:
* a hash of the form:
* {:value => String (value of bind parameter)
* :format => Fixnum (0 for text, 1 for binary)
* }
* or, it may be a String. If it is a string, that is equivalent to the hash:
* { :value => <string value>, :format => 0 }
*
* PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
* inside the SQL query. The 0th element of the +params+ array is bound
* to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
*
* The optional +result_format+ should be 0 for text results, 1
* for binary.
*/
static VALUE
pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
{
PGconn *conn = get_pgconn(self);
PGresult *result = NULL;
VALUE rb_pgresult;
VALUE name, params, in_res_fmt;
VALUE param, param_value, param_format;
VALUE param_value_tmp;
VALUE sym_value, sym_format;
VALUE gc_array;
int i = 0;
int nParams;
char ** paramValues;
int *paramLengths;
int *paramFormats;
int resultFormat;
rb_scan_args(argc, argv, "12", &name, ¶ms, &in_res_fmt);
Check_Type(name, T_STRING);
if(NIL_P(params)) {
params = rb_ary_new2(0);
resultFormat = 0;
}
else {
Check_Type(params, T_ARRAY);
}
if(NIL_P(in_res_fmt)) {
resultFormat = 0;
}
else {
resultFormat = NUM2INT(in_res_fmt);
}
gc_array = rb_ary_new();
rb_gc_register_address(&gc_array);
sym_value = ID2SYM(rb_intern("value"));
sym_format = ID2SYM(rb_intern("format"));
nParams = RARRAY_LEN(params);
paramValues = ALLOC_N(char *, nParams);
paramLengths = ALLOC_N(int, nParams);
paramFormats = ALLOC_N(int, nParams);
for(i = 0; i < nParams; i++) {
param = rb_ary_entry(params, i);
if (TYPE(param) == T_HASH) {
param_value_tmp = rb_hash_aref(param, sym_value);
if(param_value_tmp == Qnil)
param_value = param_value_tmp;
else
param_value = rb_obj_as_string(param_value_tmp);
param_format = rb_hash_aref(param, sym_format);
}
else {
if(param == Qnil)
param_value = param;
else
param_value = rb_obj_as_string(param);
param_format = INT2NUM(0);
}
if(param_value == Qnil) {
paramValues[i] = NULL;
paramLengths[i] = 0;
}
else {
Check_Type(param_value, T_STRING);
/* make sure param_value doesn't get freed by the GC */
rb_ary_push(gc_array, param_value);
paramValues[i] = StringValuePtr(param_value);
paramLengths[i] = RSTRING_LEN(param_value);
}
if(param_format == Qnil)
paramFormats[i] = 0;
else
paramFormats[i] = NUM2INT(param_format);
}
result = PQexecPrepared(conn, StringValuePtr(name), nParams,
(const char * const *)paramValues, paramLengths, paramFormats,
resultFormat);
rb_gc_unregister_address(&gc_array);
xfree(paramValues);
xfree(paramLengths);
xfree(paramFormats);
rb_pgresult = new_pgresult(result);
pgresult_check(self, rb_pgresult);
if (rb_block_given_p()) {
return rb_ensure(yield_pgresult, rb_pgresult,
pgresult_clear, rb_pgresult);
}
return rb_pgresult;
}