VALUE db_postgres_statement_execute(int argc, VALUE *argv, VALUE self) { PGresult *result; PGconn *connection; char **bind_args_data = 0; int n, *bind_args_size = 0, *bind_args_fmt = 0; VALUE bind, data, typecast_bind; Statement *s = db_postgres_statement_handle_safe(self); connection = db_postgres_adapter_handle_safe(s->adapter)->connection; rb_scan_args(argc, argv, "00*", &bind); typecast_bind = rb_ary_new(); rb_gc_register_address(&typecast_bind); rb_gc_register_address(&bind); if (RARRAY_LEN(bind) > 0) { bind_args_size = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_fmt = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_data = (char **) malloc(sizeof(char *) * RARRAY_LEN(bind)); for (n = 0; n < RARRAY_LEN(bind); n++) { data = rb_ary_entry(bind, n); if (NIL_P(data)) { bind_args_size[n] = 0; bind_args_data[n] = 0; bind_args_fmt[n] = 0; } else { if (rb_obj_is_kind_of(data, rb_cIO) || rb_obj_is_kind_of(data, cStringIO)) bind_args_fmt[n] = 1; else bind_args_fmt[n] = 0; data = typecast_to_string(data); rb_ary_push(typecast_bind, data); bind_args_size[n] = RSTRING_LEN(data); bind_args_data[n] = RSTRING_PTR(data); } } Query q = { .connection = connection, .command = s->id, .n_args = RARRAY_LEN(bind), .data = bind_args_data, .size = bind_args_size, .format = bind_args_fmt }; result = (PGresult *)GVL_NOLOCK(nogvl_pq_exec_prepared, &q, RUBY_UBF_IO, 0); free(bind_args_fmt); free(bind_args_size); free(bind_args_data); } else {
VALUE db_postgres_adapter_execute(int argc, VALUE *argv, VALUE self) { char **bind_args_data = 0; int n, *bind_args_size = 0, *bind_args_fmt = 0; PGresult *result; VALUE sql, bind, data; Adapter *a = db_postgres_adapter_handle_safe(self); rb_scan_args(argc, argv, "10*", &sql, &bind); if (!a->native) sql = db_postgres_normalized_sql(sql); if (RARRAY_LEN(bind) > 0) { bind_args_size = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_fmt = (int *) malloc(sizeof(int) * RARRAY_LEN(bind)); bind_args_data = (char **) malloc(sizeof(char *) * RARRAY_LEN(bind)); rb_gc_register_address(&bind); for (n = 0; n < RARRAY_LEN(bind); n++) { data = rb_ary_entry(bind, n); if (NIL_P(data)) { bind_args_size[n] = 0; bind_args_data[n] = 0; bind_args_fmt[n] = 0; } else { if (rb_obj_is_kind_of(data, rb_cIO) || rb_obj_is_kind_of(data, cStringIO)) bind_args_fmt[n] = 1; else bind_args_fmt[n] = 0; data = typecast_to_string(data); bind_args_size[n] = RSTRING_LEN(data); bind_args_data[n] = RSTRING_PTR(data); } } Query q = { .connection = a->connection, .command = CSTRING(sql), .n_args = RARRAY_LEN(bind), .data = bind_args_data, .size = bind_args_size, .format = bind_args_fmt }; result = (PGresult *)rb_thread_blocking_region(nogvl_pq_exec_params, &q, RUBY_UBF_IO, 0); rb_gc_unregister_address(&bind); free(bind_args_size); free(bind_args_data); free(bind_args_fmt); } else {
VALUE db_postgres_statement_initialize(VALUE self, VALUE adapter, VALUE sql) { PGresult *result; Statement *s = db_postgres_statement_handle(self); Adapter *a = db_postgres_adapter_handle_safe(adapter); snprintf(s->id, 128, "s%s", CSTRING(rb_uuid_string())); s->adapter = adapter; if (!a->native) sql = db_postgres_normalized_sql(sql); result = PQprepare(a->connection, s->id, CSTRING(sql), 0, 0); db_postgres_check_result(result); PQclear(result); return self; }
VALUE db_postgres_statement_release(VALUE self) { char command[256]; PGresult *result; PGconn *connection; Statement *s = db_postgres_statement_handle_safe(self); connection = db_postgres_adapter_handle_safe(s->adapter)->connection; if (connection && PQstatus(connection) == CONNECTION_OK) { snprintf(command, 256, "deallocate %s", s->id); result = PQexec(connection, command); db_postgres_check_result(result); PQclear(result); return Qtrue; } return Qfalse; }