Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 42 additions & 16 deletions ext/pg_connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,13 @@ pgconn_make_conninfo_array( const PQconninfoOption *options )
return ary;
}

static const char *pg_cstr_enc(VALUE str, int enc_idx){
static const char *pg_cstr_enc(VALUE str, int enc_idx, VALUE *transcoded_str){
const char *ptr = StringValueCStr(str);
if( ENCODING_GET(str) == enc_idx ){
return ptr;
} else {
str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
return StringValueCStr(str);
*transcoded_str = rb_str_export_to_enc(str, rb_enc_from_index(enc_idx));
return StringValueCStr(*transcoded_str);
}
}

Expand Down Expand Up @@ -1142,8 +1142,10 @@ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
/* If called with no or nil parameters, use PQexec for compatibility */
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
VALUE query_str = argv[0];
VALUE transcoded_str;

result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx, &transcoded_str));
RB_GC_GUARD(transcoded_str);
rb_pgresult = pg_new_result(result, self);
pg_result_check(rb_pgresult);
if (rb_block_given_p()) {
Expand Down Expand Up @@ -1440,6 +1442,7 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
PGresult *result = NULL;
VALUE rb_pgresult;
VALUE command, in_res_fmt;
VALUE transcoded_str;
int nParams;
int resultFormat;
struct query_params_data paramsData = { this->enc_idx };
Expand All @@ -1461,9 +1464,10 @@ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
nParams = alloc_query_params( &paramsData );

result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);

RB_GC_GUARD(transcoded_str);
free_query_params( &paramsData );

rb_pgresult = pg_new_result(result, self);
Expand Down Expand Up @@ -1492,6 +1496,7 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
VALUE rb_pgresult;
VALUE name, command, in_paramtypes;
VALUE param;
VALUE transcoded_str1, transcoded_str2;
int i = 0;
int nParams = 0;
Oid *paramTypes = NULL;
Expand All @@ -1500,8 +1505,8 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
int enc_idx = this->enc_idx;

rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
name_cstr = pg_cstr_enc(name, enc_idx);
command_cstr = pg_cstr_enc(command, enc_idx);
name_cstr = pg_cstr_enc(name, enc_idx, &transcoded_str1);
command_cstr = pg_cstr_enc(command, enc_idx, &transcoded_str2);

if(! NIL_P(in_paramtypes)) {
Check_Type(in_paramtypes, T_ARRAY);
Expand All @@ -1517,6 +1522,8 @@ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
}
result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);

RB_GC_GUARD(transcoded_str1);
RB_GC_GUARD(transcoded_str2);
xfree(paramTypes);

rb_pgresult = pg_new_result(result, self);
Expand All @@ -1540,6 +1547,7 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
PGresult *result = NULL;
VALUE rb_pgresult;
VALUE name, in_res_fmt;
VALUE transcoded_str;
int nParams;
int resultFormat;
struct query_params_data paramsData = { this->enc_idx };
Expand All @@ -1555,10 +1563,11 @@ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
nParams = alloc_query_params( &paramsData );

result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
resultFormat);

RB_GC_GUARD(transcoded_str);
free_query_params( &paramsData );

rb_pgresult = pg_new_result(result, self);
Expand All @@ -1575,9 +1584,13 @@ pgconn_sync_describe_close_prepared_portal(VALUE self, VALUE name, PGresult *(*f
{
PGresult *result;
VALUE rb_pgresult;
VALUE transcoded_str;
t_pg_connection *this = pg_get_connection_safe( self );
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx, &transcoded_str);

result = func(this->pgconn, stmt);

RB_GC_GUARD(transcoded_str);
rb_pgresult = pg_new_result(result, self);
pg_result_check(rb_pgresult);
return rb_pgresult;
Expand Down Expand Up @@ -1974,13 +1987,15 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
static VALUE
pgconn_send_query(int argc, VALUE *argv, VALUE self)
{
VALUE transcoded_str;
t_pg_connection *this = pg_get_connection_safe( self );

/* If called with no or nil parameters, use PQexec for compatibility */
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx, &transcoded_str)) == 0)
pg_raise_conn_error( rb_eUnableToSend, self, "PQsendQuery %s", PQerrorMessage(this->pgconn));

RB_GC_GUARD(transcoded_str);
pgconn_wait_for_flush( self );
return Qnil;
}
Expand Down Expand Up @@ -2037,6 +2052,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
t_pg_connection *this = pg_get_connection_safe( self );
int result;
VALUE command, in_res_fmt;
VALUE transcoded_str;
int nParams;
int resultFormat;
struct query_params_data paramsData = { this->enc_idx };
Expand All @@ -2048,9 +2064,10 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
nParams = alloc_query_params( &paramsData );

result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx, &transcoded_str), nParams, paramsData.types,
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);

RB_GC_GUARD(transcoded_str);
free_query_params( &paramsData );

if(result == 0)
Expand Down Expand Up @@ -2087,6 +2104,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
int result;
VALUE name, command, in_paramtypes;
VALUE param;
VALUE transcoded_str1, transcoded_str2;
int i = 0;
int nParams = 0;
Oid *paramTypes = NULL;
Expand All @@ -2095,8 +2113,8 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
int enc_idx = this->enc_idx;

rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
name_cstr = pg_cstr_enc(name, enc_idx);
command_cstr = pg_cstr_enc(command, enc_idx);
name_cstr = pg_cstr_enc(name, enc_idx, &transcoded_str1);
command_cstr = pg_cstr_enc(command, enc_idx, &transcoded_str2);

if(! NIL_P(in_paramtypes)) {
Check_Type(in_paramtypes, T_ARRAY);
Expand All @@ -2112,6 +2130,8 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
}
result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);

RB_GC_GUARD(transcoded_str1);
RB_GC_GUARD(transcoded_str2);
xfree(paramTypes);

if(result == 0) {
Expand Down Expand Up @@ -2159,6 +2179,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
t_pg_connection *this = pg_get_connection_safe( self );
int result;
VALUE name, in_res_fmt;
VALUE transcoded_str;
int nParams;
int resultFormat;
struct query_params_data paramsData = { this->enc_idx };
Expand All @@ -2174,10 +2195,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
nParams = alloc_query_params( &paramsData );

result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx, &transcoded_str), nParams,
(const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
resultFormat);

RB_GC_GUARD(transcoded_str);
free_query_params( &paramsData );

if(result == 0)
Expand All @@ -2191,12 +2213,14 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
static VALUE
pgconn_send_describe_close_prepared_portal(VALUE self, VALUE name, int (*func)(PGconn *, const char *), const char *funame)
{
VALUE transcoded_str;
t_pg_connection *this = pg_get_connection_safe( self );
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx);
const char *stmt = NIL_P(name) ? NULL : pg_cstr_enc(name, this->enc_idx, &transcoded_str);
/* returns 0 on failure */
if(func(this->pgconn, stmt) == 0)
pg_raise_conn_error( rb_eUnableToSend, self, "%s %s", funame, PQerrorMessage(this->pgconn));

RB_GC_GUARD(transcoded_str);
pgconn_wait_for_flush( self );
return Qnil;
}
Expand Down Expand Up @@ -2773,19 +2797,21 @@ static VALUE
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
{
VALUE str;
VALUE transcoded_str;
int ret;
const char *error_message = NULL;
t_pg_connection *this = pg_get_connection_safe( self );

if (rb_scan_args(argc, argv, "01", &str) == 0)
error_message = NULL;
else
error_message = pg_cstr_enc(str, this->enc_idx);
error_message = pg_cstr_enc(str, this->enc_idx, &transcoded_str);

ret = gvl_PQputCopyEnd(this->pgconn, error_message);
if(ret == -1)
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));

RB_GC_GUARD(transcoded_str);
return (ret) ? Qtrue : Qfalse;
}

Expand Down
Loading