pg 0.15.1-x64-mingw32 → 0.16.0-x64-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +395 -1
- data/History.rdoc +30 -3
- data/Manifest.txt +4 -0
- data/Rakefile +30 -10
- data/ext/errorcodes.def +931 -0
- data/ext/errorcodes.rb +45 -0
- data/ext/errorcodes.txt +463 -0
- data/ext/extconf.rb +11 -5
- data/ext/gvl_wrappers.c +6 -0
- data/ext/gvl_wrappers.h +47 -21
- data/ext/pg.c +29 -9
- data/ext/pg.h +30 -0
- data/ext/pg_connection.c +104 -44
- data/ext/pg_errors.c +89 -0
- data/ext/pg_result.c +48 -67
- data/lib/2.0/pg_ext.so +0 -0
- data/lib/pg.rb +1 -1
- data/spec/lib/helpers.rb +11 -2
- data/spec/pg/connection_spec.rb +113 -8
- data/spec/pg/result_spec.rb +69 -2
- data/spec/pg_spec.rb +13 -0
- metadata +16 -56
- metadata.gz.sig +0 -0
data/ext/extconf.rb
CHANGED
@@ -27,17 +27,22 @@ if ENV['CROSS_COMPILING']
|
|
27
27
|
have_library( 'ssl', 'SSL_new' ) && append_library( $libs, 'ssl' )
|
28
28
|
end
|
29
29
|
|
30
|
-
dir_config 'pg'
|
31
|
-
|
32
30
|
if pgconfig = ( with_config('pg-config') || with_config('pg_config') || find_executable('pg_config') )
|
33
31
|
$stderr.puts "Using config values from %s" % [ pgconfig ]
|
34
|
-
|
35
|
-
|
32
|
+
incdir = `"#{pgconfig}" --includedir`.chomp
|
36
33
|
libdir = `"#{pgconfig}" --libdir`.chomp
|
37
|
-
|
34
|
+
dir_config 'pg', incdir, libdir
|
35
|
+
|
36
|
+
# Try to use runtime path linker option, even if RbConfig doesn't know about it.
|
37
|
+
# The rpath option is usually set implicit by dir_config(), but so far not
|
38
|
+
# on MacOS-X.
|
39
|
+
if RbConfig::CONFIG["RPATHFLAG"].to_s.empty? && try_link('int main() {return 0;}', " -Wl,-rpath,#{libdir}")
|
40
|
+
$LDFLAGS << " -Wl,-rpath,#{libdir}"
|
41
|
+
end
|
38
42
|
else
|
39
43
|
$stderr.puts "No pg_config... trying anyway. If building fails, please try again with",
|
40
44
|
" --with-pg-config=/path/to/pg_config"
|
45
|
+
dir_config 'pg'
|
41
46
|
end
|
42
47
|
|
43
48
|
find_header( 'libpq-fe.h' ) or abort "Can't find the 'libpq-fe.h header"
|
@@ -78,6 +83,7 @@ have_func 'rb_w32_wrap_io_handle'
|
|
78
83
|
|
79
84
|
have_const 'PGRES_COPY_BOTH', 'libpq-fe.h'
|
80
85
|
have_const 'PGRES_SINGLE_TUPLE', 'libpq-fe.h'
|
86
|
+
have_const 'PG_DIAG_TABLE_NAME', 'libpq-fe.h'
|
81
87
|
|
82
88
|
$defs.push( "-DHAVE_ST_NOTIFY_EXTRA" ) if
|
83
89
|
have_struct_member 'struct pgNotify', 'extra', 'libpq-fe.h'
|
data/ext/gvl_wrappers.c
CHANGED
@@ -11,3 +11,9 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB );
|
|
11
11
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_WRAPPER_STRUCT );
|
12
12
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_SKELETON );
|
13
13
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVLCB_STUB );
|
14
|
+
|
15
|
+
void ubf_cancel_running_command(void *c)
|
16
|
+
{
|
17
|
+
PGconn *conn = (PGconn*) c;
|
18
|
+
PQrequestCancel(conn);
|
19
|
+
}
|
data/ext/gvl_wrappers.h
CHANGED
@@ -24,6 +24,8 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
24
24
|
rb_unblock_function_t *ubf, void *data2);
|
25
25
|
#endif
|
26
26
|
|
27
|
+
void ubf_cancel_running_command(void *c);
|
28
|
+
|
27
29
|
#define DEFINE_PARAM_LIST1(type, name) \
|
28
30
|
name,
|
29
31
|
|
@@ -36,7 +38,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
36
38
|
#define DEFINE_PARAM_DECL(type, name) \
|
37
39
|
type name;
|
38
40
|
|
39
|
-
#define DEFINE_GVL_WRAPPER_STRUCT(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
41
|
+
#define DEFINE_GVL_WRAPPER_STRUCT(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
40
42
|
struct gvl_wrapper_##name##_params { \
|
41
43
|
struct { \
|
42
44
|
FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_DECL) \
|
@@ -45,7 +47,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
45
47
|
when_non_void( rettype retval; ) \
|
46
48
|
};
|
47
49
|
|
48
|
-
#define DEFINE_GVL_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
50
|
+
#define DEFINE_GVL_SKELETON(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
49
51
|
static void * gvl_##name##_skeleton( void *data ){ \
|
50
52
|
struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
|
51
53
|
when_non_void( p->retval = ) \
|
@@ -54,25 +56,25 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
54
56
|
}
|
55
57
|
|
56
58
|
#if defined(HAVE_RB_THREAD_CALL_WITHOUT_GVL)
|
57
|
-
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
59
|
+
#define DEFINE_GVL_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
58
60
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
59
61
|
struct gvl_wrapper_##name##_params params = { \
|
60
62
|
{FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
|
61
63
|
}; \
|
62
|
-
rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms,
|
64
|
+
rb_thread_call_without_gvl(gvl_##name##_skeleton, ¶ms, cancel_params); \
|
63
65
|
when_non_void( return params.retval; ) \
|
64
66
|
}
|
65
67
|
#else
|
66
|
-
#define DEFINE_GVL_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
68
|
+
#define DEFINE_GVL_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
67
69
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
68
70
|
return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
69
71
|
}
|
70
72
|
#endif
|
71
73
|
|
72
|
-
#define DEFINE_GVL_STUB_DECL(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
74
|
+
#define DEFINE_GVL_STUB_DECL(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
73
75
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname);
|
74
76
|
|
75
|
-
#define DEFINE_GVLCB_SKELETON(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
77
|
+
#define DEFINE_GVLCB_SKELETON(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
76
78
|
static void * gvl_##name##_skeleton( void *data ){ \
|
77
79
|
struct gvl_wrapper_##name##_params *p = (struct gvl_wrapper_##name##_params*)data; \
|
78
80
|
when_non_void( p->retval = ) \
|
@@ -81,7 +83,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
81
83
|
}
|
82
84
|
|
83
85
|
#if defined(HAVE_RB_THREAD_CALL_WITH_GVL)
|
84
|
-
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
86
|
+
#define DEFINE_GVLCB_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
85
87
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
86
88
|
struct gvl_wrapper_##name##_params params = { \
|
87
89
|
{FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname}, when_non_void((rettype)0) \
|
@@ -90,7 +92,7 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
90
92
|
when_non_void( return params.retval; ) \
|
91
93
|
}
|
92
94
|
#else
|
93
|
-
#define DEFINE_GVLCB_STUB(name, when_non_void, rettype, lastparamtype, lastparamname) \
|
95
|
+
#define DEFINE_GVLCB_STUB(name, cancel_params, when_non_void, rettype, lastparamtype, lastparamname) \
|
94
96
|
rettype gvl_##name(FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST3) lastparamtype lastparamname){ \
|
95
97
|
return name( FOR_EACH_PARAM_OF_##name(DEFINE_PARAM_LIST1) lastparamname ); \
|
96
98
|
}
|
@@ -99,11 +101,26 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
99
101
|
#define GVL_TYPE_VOID(string)
|
100
102
|
#define GVL_TYPE_NONVOID(string) string
|
101
103
|
|
104
|
+
#define GVL_CANCELABLE ubf_cancel_running_command, conn
|
105
|
+
#define GVL_NONCANCELABLE RUBY_UBF_IO, 0
|
106
|
+
|
102
107
|
|
103
108
|
/*
|
104
109
|
* Definitions of blocking functions and their parameters
|
105
110
|
*/
|
106
111
|
|
112
|
+
#define FOR_EACH_PARAM_OF_PQconnectdb(param)
|
113
|
+
|
114
|
+
#define FOR_EACH_PARAM_OF_PQconnectStart(param)
|
115
|
+
|
116
|
+
#define FOR_EACH_PARAM_OF_PQconnectPoll(param)
|
117
|
+
|
118
|
+
#define FOR_EACH_PARAM_OF_PQreset(param)
|
119
|
+
|
120
|
+
#define FOR_EACH_PARAM_OF_PQresetStart(param)
|
121
|
+
|
122
|
+
#define FOR_EACH_PARAM_OF_PQresetPoll(param)
|
123
|
+
|
107
124
|
#define FOR_EACH_PARAM_OF_PQexec(param) \
|
108
125
|
param(PGconn *, conn)
|
109
126
|
|
@@ -149,18 +166,27 @@ extern void *rb_thread_call_without_gvl(void *(*func)(void *), void *data1,
|
|
149
166
|
param(PGconn *, conn) \
|
150
167
|
param(char **, buffer)
|
151
168
|
|
169
|
+
#define FOR_EACH_PARAM_OF_PQnotifies(param)
|
170
|
+
|
152
171
|
/* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
153
172
|
#define FOR_EACH_BLOCKING_FUNCTION(function) \
|
154
|
-
function(
|
155
|
-
function(
|
156
|
-
function(
|
157
|
-
function(
|
158
|
-
function(
|
159
|
-
function(
|
160
|
-
function(
|
161
|
-
function(
|
162
|
-
function(
|
163
|
-
function(
|
173
|
+
function(PQconnectdb, GVL_NONCANCELABLE, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
|
174
|
+
function(PQconnectStart, GVL_NONCANCELABLE, GVL_TYPE_NONVOID, PGconn *, const char *, conninfo) \
|
175
|
+
function(PQconnectPoll, GVL_CANCELABLE, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
|
176
|
+
function(PQreset, GVL_CANCELABLE, GVL_TYPE_VOID, void, PGconn *, conn) \
|
177
|
+
function(PQresetStart, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, PGconn *, conn) \
|
178
|
+
function(PQresetPoll, GVL_CANCELABLE, GVL_TYPE_NONVOID, PostgresPollingStatusType, PGconn *, conn) \
|
179
|
+
function(PQexec, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
|
180
|
+
function(PQexecParams, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
181
|
+
function(PQexecPrepared, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
|
182
|
+
function(PQprepare, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
|
183
|
+
function(PQdescribePrepared, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
|
184
|
+
function(PQdescribePortal, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
|
185
|
+
function(PQgetResult, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
|
186
|
+
function(PQputCopyData, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, nbytes) \
|
187
|
+
function(PQputCopyEnd, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, const char *, errormsg) \
|
188
|
+
function(PQgetCopyData, GVL_CANCELABLE, GVL_TYPE_NONVOID, int, int, async) \
|
189
|
+
function(PQnotifies, GVL_CANCELABLE, GVL_TYPE_NONVOID, PGnotify *, PGconn *, conn);
|
164
190
|
|
165
191
|
FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
|
166
192
|
|
@@ -177,8 +203,8 @@ FOR_EACH_BLOCKING_FUNCTION( DEFINE_GVL_STUB_DECL );
|
|
177
203
|
|
178
204
|
/* function( name, void_or_nonvoid, returntype, lastparamtype, lastparamname ) */
|
179
205
|
#define FOR_EACH_CALLBACK_FUNCTION(function) \
|
180
|
-
function(notice_processor_proxy
|
181
|
-
function(notice_receiver_proxy
|
206
|
+
function(notice_processor_proxy,, GVL_TYPE_VOID, void, const char *, message) \
|
207
|
+
function(notice_receiver_proxy,, GVL_TYPE_VOID, void, const PGresult *, result) \
|
182
208
|
|
183
209
|
FOR_EACH_CALLBACK_FUNCTION( DEFINE_GVL_STUB_DECL );
|
184
210
|
|
data/ext/pg.c
CHANGED
@@ -48,7 +48,6 @@
|
|
48
48
|
#include "pg.h"
|
49
49
|
|
50
50
|
VALUE rb_mPG;
|
51
|
-
VALUE rb_ePGerror;
|
52
51
|
VALUE rb_mPGconstants;
|
53
52
|
|
54
53
|
|
@@ -300,7 +299,6 @@ void
|
|
300
299
|
Init_pg_ext()
|
301
300
|
{
|
302
301
|
rb_mPG = rb_define_module( "PG" );
|
303
|
-
rb_ePGerror = rb_define_class_under( rb_mPG, "Error", rb_eStandardError );
|
304
302
|
rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" );
|
305
303
|
|
306
304
|
/*************************
|
@@ -313,13 +311,6 @@ Init_pg_ext()
|
|
313
311
|
SINGLETON_ALIAS( rb_mPG, "is_threadsafe?", "isthreadsafe" );
|
314
312
|
SINGLETON_ALIAS( rb_mPG, "threadsafe?", "isthreadsafe" );
|
315
313
|
|
316
|
-
/*************************
|
317
|
-
* PG::Error
|
318
|
-
*************************/
|
319
|
-
rb_define_alias( rb_ePGerror, "error", "message" );
|
320
|
-
rb_define_attr( rb_ePGerror, "connection", 1, 0 );
|
321
|
-
rb_define_attr( rb_ePGerror, "result", 1, 0 );
|
322
|
-
|
323
314
|
/****** PG::Connection CLASS CONSTANTS: Connection Status ******/
|
324
315
|
|
325
316
|
/* Connection succeeded */
|
@@ -506,6 +497,34 @@ Init_pg_ext()
|
|
506
497
|
* function reporting the error. */
|
507
498
|
rb_define_const(rb_mPGconstants, "PG_DIAG_SOURCE_FUNCTION", INT2FIX(PG_DIAG_SOURCE_FUNCTION));
|
508
499
|
|
500
|
+
#ifdef HAVE_CONST_PG_DIAG_TABLE_NAME
|
501
|
+
/* #result_error_field argument constant: If the error was associated with a
|
502
|
+
* specific database object, the name of the schema containing that object, if any. */
|
503
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_SCHEMA_NAME", INT2FIX(PG_DIAG_SCHEMA_NAME));
|
504
|
+
|
505
|
+
/* #result_error_field argument constant: If the error was associated with a
|
506
|
+
*specific table, the name of the table. (When this field is present, the schema name
|
507
|
+
* field provides the name of the table's schema.) */
|
508
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_TABLE_NAME", INT2FIX(PG_DIAG_TABLE_NAME));
|
509
|
+
|
510
|
+
/* #result_error_field argument constant: If the error was associated with a
|
511
|
+
* specific table column, the name of the column. (When this field is present, the
|
512
|
+
* schema and table name fields identify the table.) */
|
513
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_COLUMN_NAME", INT2FIX(PG_DIAG_COLUMN_NAME));
|
514
|
+
|
515
|
+
/* #result_error_field argument constant: If the error was associated with a
|
516
|
+
* specific datatype, the name of the datatype. (When this field is present, the
|
517
|
+
* schema name field provides the name of the datatype's schema.) */
|
518
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_DATATYPE_NAME", INT2FIX(PG_DIAG_DATATYPE_NAME));
|
519
|
+
|
520
|
+
/* #result_error_field argument constant: If the error was associated with a
|
521
|
+
* specific constraint, the name of the constraint. The table or domain that the
|
522
|
+
* constraint belongs to is reported using the fields listed above. (For this
|
523
|
+
* purpose, indexes are treated as constraints, even if they weren't created with
|
524
|
+
* constraint syntax.) */
|
525
|
+
rb_define_const(rb_mPGconstants, "PG_DIAG_CONSTRAINT_NAME", INT2FIX(PG_DIAG_CONSTRAINT_NAME));
|
526
|
+
#endif
|
527
|
+
|
509
528
|
/* Invalid OID constant */
|
510
529
|
rb_define_const(rb_mPGconstants, "INVALID_OID", INT2FIX(InvalidOid));
|
511
530
|
rb_define_const(rb_mPGconstants, "InvalidOid", INT2FIX(InvalidOid));
|
@@ -521,5 +540,6 @@ Init_pg_ext()
|
|
521
540
|
/* Initialize the main extension classes */
|
522
541
|
init_pg_connection();
|
523
542
|
init_pg_result();
|
543
|
+
init_pg_errors();
|
524
544
|
}
|
525
545
|
|
data/ext/pg.h
CHANGED
@@ -66,6 +66,30 @@
|
|
66
66
|
# include "ruby/io.h"
|
67
67
|
#endif
|
68
68
|
|
69
|
+
#ifndef timeradd
|
70
|
+
#define timeradd(a, b, result) \
|
71
|
+
do { \
|
72
|
+
(result)->tv_sec = (a)->tv_sec + (b)->tv_sec; \
|
73
|
+
(result)->tv_usec = (a)->tv_usec + (b)->tv_usec; \
|
74
|
+
if ((result)->tv_usec >= 1000000L) { \
|
75
|
+
++(result)->tv_sec; \
|
76
|
+
(result)->tv_usec -= 1000000L; \
|
77
|
+
} \
|
78
|
+
} while (0)
|
79
|
+
#endif
|
80
|
+
|
81
|
+
#ifndef timersub
|
82
|
+
#define timersub(a, b, result) \
|
83
|
+
do { \
|
84
|
+
(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
|
85
|
+
(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
|
86
|
+
if ((result)->tv_usec < 0) { \
|
87
|
+
--(result)->tv_sec; \
|
88
|
+
(result)->tv_usec += 1000000L; \
|
89
|
+
} \
|
90
|
+
} while (0)
|
91
|
+
#endif
|
92
|
+
|
69
93
|
/* PostgreSQL headers */
|
70
94
|
#include "libpq-fe.h"
|
71
95
|
#include "libpq/libpq-fs.h" /* large-object interface */
|
@@ -85,9 +109,13 @@ typedef long suseconds_t;
|
|
85
109
|
|
86
110
|
extern VALUE rb_mPG;
|
87
111
|
extern VALUE rb_ePGerror;
|
112
|
+
extern VALUE rb_eServerError;
|
113
|
+
extern VALUE rb_eUnableToSend;
|
114
|
+
extern VALUE rb_eConnectionBad;
|
88
115
|
extern VALUE rb_mPGconstants;
|
89
116
|
extern VALUE rb_cPGconn;
|
90
117
|
extern VALUE rb_cPGresult;
|
118
|
+
extern VALUE rb_hErrors;
|
91
119
|
|
92
120
|
|
93
121
|
/***************************************************************************
|
@@ -105,6 +133,8 @@ void Init_pg_ext _(( void ));
|
|
105
133
|
|
106
134
|
void init_pg_connection _(( void ));
|
107
135
|
void init_pg_result _(( void ));
|
136
|
+
void init_pg_errors _(( void ));
|
137
|
+
VALUE lookup_error_class _(( const char *sqlstate ));
|
108
138
|
|
109
139
|
PGconn *pg_get_pgconn _(( VALUE ));
|
110
140
|
|
data/ext/pg_connection.c
CHANGED
@@ -40,7 +40,7 @@ pg_get_pgconn( VALUE self )
|
|
40
40
|
PGconn *conn = pgconn_check( self );
|
41
41
|
|
42
42
|
if ( !conn )
|
43
|
-
rb_raise(
|
43
|
+
rb_raise( rb_eConnectionBad, "connection is closed" );
|
44
44
|
|
45
45
|
return conn;
|
46
46
|
}
|
@@ -58,7 +58,7 @@ pgconn_close_socket_io( VALUE self )
|
|
58
58
|
#if defined(_WIN32) && defined(HAVE_RB_W32_WRAP_IO_HANDLE)
|
59
59
|
int ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
|
60
60
|
if( rb_w32_unwrap_io_handle(ruby_sd) ){
|
61
|
-
rb_raise(
|
61
|
+
rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
|
62
62
|
}
|
63
63
|
#endif
|
64
64
|
rb_funcall( socket_io, rb_intern("close"), 0 );
|
@@ -113,7 +113,11 @@ pgconn_gc_free( PGconn *conn )
|
|
113
113
|
static VALUE
|
114
114
|
pgconn_s_allocate( VALUE klass )
|
115
115
|
{
|
116
|
-
|
116
|
+
VALUE self = Data_Wrap_Struct( klass, NULL, pgconn_gc_free, NULL );
|
117
|
+
rb_iv_set( self, "@socket_io", Qnil );
|
118
|
+
rb_iv_set( self, "@notice_receiver", Qnil);
|
119
|
+
rb_iv_set( self, "@notice_processor", Qnil);
|
120
|
+
return self;
|
117
121
|
}
|
118
122
|
|
119
123
|
|
@@ -182,16 +186,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
|
|
182
186
|
VALUE error;
|
183
187
|
|
184
188
|
conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
|
185
|
-
conn =
|
189
|
+
conn = gvl_PQconnectdb(StringValuePtr(conninfo));
|
186
190
|
|
187
191
|
if(conn == NULL)
|
188
|
-
rb_raise(rb_ePGerror, "
|
192
|
+
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
|
189
193
|
|
190
194
|
Check_Type(self, T_DATA);
|
191
195
|
DATA_PTR(self) = conn;
|
192
196
|
|
193
197
|
if (PQstatus(conn) == CONNECTION_BAD) {
|
194
|
-
error = rb_exc_new2(
|
198
|
+
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
195
199
|
rb_iv_set(error, "@connection", self);
|
196
200
|
rb_exc_raise(error);
|
197
201
|
}
|
@@ -236,7 +240,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
236
240
|
*/
|
237
241
|
rb_conn = pgconn_s_allocate( klass );
|
238
242
|
conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
|
239
|
-
conn =
|
243
|
+
conn = gvl_PQconnectStart( StringValuePtr(conninfo) );
|
240
244
|
|
241
245
|
if( conn == NULL )
|
242
246
|
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
|
@@ -245,7 +249,7 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
245
249
|
DATA_PTR(rb_conn) = conn;
|
246
250
|
|
247
251
|
if ( PQstatus(conn) == CONNECTION_BAD ) {
|
248
|
-
error = rb_exc_new2(
|
252
|
+
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
249
253
|
rb_iv_set(error, "@connection", rb_conn);
|
250
254
|
rb_exc_raise(error);
|
251
255
|
}
|
@@ -415,7 +419,7 @@ static VALUE
|
|
415
419
|
pgconn_connect_poll(VALUE self)
|
416
420
|
{
|
417
421
|
PostgresPollingStatusType status;
|
418
|
-
status =
|
422
|
+
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
419
423
|
return INT2FIX((int)status);
|
420
424
|
}
|
421
425
|
|
@@ -460,7 +464,7 @@ static VALUE
|
|
460
464
|
pgconn_reset( VALUE self )
|
461
465
|
{
|
462
466
|
pgconn_close_socket_io( self );
|
463
|
-
|
467
|
+
gvl_PQreset( pg_get_pgconn(self) );
|
464
468
|
return self;
|
465
469
|
}
|
466
470
|
|
@@ -478,8 +482,8 @@ static VALUE
|
|
478
482
|
pgconn_reset_start(VALUE self)
|
479
483
|
{
|
480
484
|
pgconn_close_socket_io( self );
|
481
|
-
if(
|
482
|
-
rb_raise(
|
485
|
+
if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
|
486
|
+
rb_raise(rb_eUnableToSend, "reset has failed");
|
483
487
|
return Qnil;
|
484
488
|
}
|
485
489
|
|
@@ -495,7 +499,7 @@ static VALUE
|
|
495
499
|
pgconn_reset_poll(VALUE self)
|
496
500
|
{
|
497
501
|
PostgresPollingStatusType status;
|
498
|
-
status =
|
502
|
+
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
499
503
|
return INT2FIX((int)status);
|
500
504
|
}
|
501
505
|
|
@@ -718,7 +722,7 @@ pgconn_socket(VALUE self)
|
|
718
722
|
{
|
719
723
|
int sd;
|
720
724
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
721
|
-
rb_raise(
|
725
|
+
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
722
726
|
return INT2NUM(sd);
|
723
727
|
}
|
724
728
|
|
@@ -749,7 +753,7 @@ pgconn_socket_io(VALUE self)
|
|
749
753
|
|
750
754
|
if ( !RTEST(socket_io) ) {
|
751
755
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
752
|
-
rb_raise(
|
756
|
+
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
753
757
|
|
754
758
|
#ifdef _WIN32
|
755
759
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
@@ -1448,6 +1452,10 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1448
1452
|
PQfreemem(escaped);
|
1449
1453
|
OBJ_INFECT(result, string);
|
1450
1454
|
|
1455
|
+
#ifdef M17N_SUPPORTED
|
1456
|
+
rb_enc_associate(result, pg_conn_enc_get( pg_get_pgconn(self) ));
|
1457
|
+
#endif
|
1458
|
+
|
1451
1459
|
return result;
|
1452
1460
|
}
|
1453
1461
|
#endif
|
@@ -1458,6 +1466,9 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1458
1466
|
* conn.escape_identifier( str ) -> String
|
1459
1467
|
*
|
1460
1468
|
* Escape an arbitrary String +str+ as an identifier.
|
1469
|
+
*
|
1470
|
+
* This method does the same as #quote_ident, but uses libpq to
|
1471
|
+
* process the string.
|
1461
1472
|
*/
|
1462
1473
|
static VALUE
|
1463
1474
|
pgconn_escape_identifier(VALUE self, VALUE string)
|
@@ -1481,6 +1492,10 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1481
1492
|
PQfreemem(escaped);
|
1482
1493
|
OBJ_INFECT(result, string);
|
1483
1494
|
|
1495
|
+
#ifdef M17N_SUPPORTED
|
1496
|
+
rb_enc_associate(result, pg_conn_enc_get( pg_get_pgconn(self) ));
|
1497
|
+
#endif
|
1498
|
+
|
1484
1499
|
return result;
|
1485
1500
|
}
|
1486
1501
|
#endif
|
@@ -1596,7 +1611,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1596
1611
|
/* If called with no parameters, use PQsendQuery */
|
1597
1612
|
if(NIL_P(params)) {
|
1598
1613
|
if(PQsendQuery(conn,StringValuePtr(command)) == 0) {
|
1599
|
-
error = rb_exc_new2(
|
1614
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1600
1615
|
rb_iv_set(error, "@connection", self);
|
1601
1616
|
rb_exc_raise(error);
|
1602
1617
|
}
|
@@ -1679,7 +1694,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
|
1679
1694
|
xfree(paramFormats);
|
1680
1695
|
|
1681
1696
|
if(result == 0) {
|
1682
|
-
error = rb_exc_new2(
|
1697
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1683
1698
|
rb_iv_set(error, "@connection", self);
|
1684
1699
|
rb_exc_raise(error);
|
1685
1700
|
}
|
@@ -1741,7 +1756,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1741
1756
|
xfree(paramTypes);
|
1742
1757
|
|
1743
1758
|
if(result == 0) {
|
1744
|
-
error = rb_exc_new2(
|
1759
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1745
1760
|
rb_iv_set(error, "@connection", self);
|
1746
1761
|
rb_exc_raise(error);
|
1747
1762
|
}
|
@@ -1864,7 +1879,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1864
1879
|
xfree(paramFormats);
|
1865
1880
|
|
1866
1881
|
if(result == 0) {
|
1867
|
-
error = rb_exc_new2(
|
1882
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1868
1883
|
rb_iv_set(error, "@connection", self);
|
1869
1884
|
rb_exc_raise(error);
|
1870
1885
|
}
|
@@ -1885,7 +1900,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1885
1900
|
PGconn *conn = pg_get_pgconn(self);
|
1886
1901
|
/* returns 0 on failure */
|
1887
1902
|
if(PQsendDescribePrepared(conn,StringValuePtr(stmt_name)) == 0) {
|
1888
|
-
error = rb_exc_new2(
|
1903
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1889
1904
|
rb_iv_set(error, "@connection", self);
|
1890
1905
|
rb_exc_raise(error);
|
1891
1906
|
}
|
@@ -1907,7 +1922,7 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
|
|
1907
1922
|
PGconn *conn = pg_get_pgconn(self);
|
1908
1923
|
/* returns 0 on failure */
|
1909
1924
|
if(PQsendDescribePortal(conn,StringValuePtr(portal)) == 0) {
|
1910
|
-
error = rb_exc_new2(
|
1925
|
+
error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
|
1911
1926
|
rb_iv_set(error, "@connection", self);
|
1912
1927
|
rb_exc_raise(error);
|
1913
1928
|
}
|
@@ -1965,7 +1980,7 @@ pgconn_consume_input(self)
|
|
1965
1980
|
PGconn *conn = pg_get_pgconn(self);
|
1966
1981
|
/* returns 0 on error */
|
1967
1982
|
if(PQconsumeInput(conn) == 0) {
|
1968
|
-
error = rb_exc_new2(
|
1983
|
+
error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
|
1969
1984
|
rb_iv_set(error, "@connection", self);
|
1970
1985
|
rb_exc_raise(error);
|
1971
1986
|
}
|
@@ -2122,7 +2137,7 @@ pgconn_notifies(VALUE self)
|
|
2122
2137
|
sym_be_pid = ID2SYM(rb_intern("be_pid"));
|
2123
2138
|
sym_extra = ID2SYM(rb_intern("extra"));
|
2124
2139
|
|
2125
|
-
notification =
|
2140
|
+
notification = gvl_PQnotifies(conn);
|
2126
2141
|
if (notification == NULL) {
|
2127
2142
|
return Qnil;
|
2128
2143
|
}
|
@@ -2199,32 +2214,46 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2199
2214
|
{
|
2200
2215
|
int sd = PQsocket( conn );
|
2201
2216
|
void *retval;
|
2217
|
+
struct timeval aborttime={0,0}, currtime, waittime;
|
2202
2218
|
DWORD timeout_milisec = INFINITE;
|
2203
2219
|
DWORD wait_ret;
|
2204
2220
|
WSAEVENT hEvent;
|
2205
2221
|
|
2206
2222
|
if ( sd < 0 )
|
2207
|
-
|
2223
|
+
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
2208
2224
|
|
2209
2225
|
hEvent = WSACreateEvent();
|
2210
2226
|
|
2211
|
-
if ( ptimeout ) {
|
2212
|
-
timeout_milisec = (DWORD)( ptimeout->tv_sec * 1e3 + ptimeout->tv_usec / 1e3 );
|
2213
|
-
}
|
2214
|
-
|
2215
2227
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2216
2228
|
if( PQconsumeInput(conn) == 0 ) {
|
2217
2229
|
WSACloseEvent( hEvent );
|
2218
|
-
rb_raise(
|
2230
|
+
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2231
|
+
}
|
2232
|
+
|
2233
|
+
if ( ptimeout ) {
|
2234
|
+
gettimeofday(&currtime, NULL);
|
2235
|
+
timeradd(&currtime, ptimeout, &aborttime);
|
2219
2236
|
}
|
2220
2237
|
|
2221
2238
|
while ( !(retval=is_readable(conn)) ) {
|
2222
2239
|
if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
|
2223
2240
|
WSACloseEvent( hEvent );
|
2224
|
-
rb_raise(
|
2241
|
+
rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
|
2225
2242
|
}
|
2226
2243
|
|
2227
|
-
|
2244
|
+
if ( ptimeout ) {
|
2245
|
+
gettimeofday(&currtime, NULL);
|
2246
|
+
timersub(&aborttime, &currtime, &waittime);
|
2247
|
+
timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
|
2248
|
+
}
|
2249
|
+
|
2250
|
+
/* Is the given timeout valid? */
|
2251
|
+
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2252
|
+
/* Wait for the socket to become readable before checking again */
|
2253
|
+
wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
|
2254
|
+
} else {
|
2255
|
+
wait_ret = WAIT_TIMEOUT;
|
2256
|
+
}
|
2228
2257
|
|
2229
2258
|
if ( wait_ret == WAIT_TIMEOUT ) {
|
2230
2259
|
WSACloseEvent( hEvent );
|
@@ -2237,16 +2266,16 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2237
2266
|
rb_thread_check_ints();
|
2238
2267
|
} else if ( wait_ret == WAIT_FAILED ) {
|
2239
2268
|
WSACloseEvent( hEvent );
|
2240
|
-
rb_raise(
|
2269
|
+
rb_raise( rb_eConnectionBad, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
|
2241
2270
|
} else {
|
2242
2271
|
WSACloseEvent( hEvent );
|
2243
|
-
rb_raise(
|
2272
|
+
rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
|
2244
2273
|
}
|
2245
2274
|
|
2246
2275
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2247
2276
|
if ( PQconsumeInput(conn) == 0 ) {
|
2248
2277
|
WSACloseEvent( hEvent );
|
2249
|
-
rb_raise(
|
2278
|
+
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2250
2279
|
}
|
2251
2280
|
}
|
2252
2281
|
|
@@ -2265,18 +2294,24 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2265
2294
|
int ret;
|
2266
2295
|
void *retval;
|
2267
2296
|
rb_fdset_t sd_rset;
|
2297
|
+
struct timeval aborttime={0,0}, currtime, waittime;
|
2268
2298
|
#ifdef _WIN32
|
2269
2299
|
rb_fdset_t crt_sd_rset;
|
2270
2300
|
#endif
|
2271
2301
|
|
2272
2302
|
if ( sd < 0 )
|
2273
|
-
|
2303
|
+
rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
|
2274
2304
|
|
2275
2305
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2276
2306
|
if ( PQconsumeInput(conn) == 0 )
|
2277
|
-
rb_raise(
|
2307
|
+
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2308
|
+
|
2309
|
+
rb_fd_init( &sd_rset );
|
2278
2310
|
|
2279
|
-
|
2311
|
+
if ( ptimeout ) {
|
2312
|
+
gettimeofday(&currtime, NULL);
|
2313
|
+
timeradd(&currtime, ptimeout, &aborttime);
|
2314
|
+
}
|
2280
2315
|
|
2281
2316
|
while ( !(retval=is_readable(conn)) ) {
|
2282
2317
|
rb_fd_zero( &sd_rset );
|
@@ -2290,8 +2325,19 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2290
2325
|
create_crt_fd(&sd_rset, &crt_sd_rset);
|
2291
2326
|
#endif
|
2292
2327
|
|
2293
|
-
|
2294
|
-
|
2328
|
+
if ( ptimeout ) {
|
2329
|
+
gettimeofday(&currtime, NULL);
|
2330
|
+
timersub(&aborttime, &currtime, &waittime);
|
2331
|
+
}
|
2332
|
+
|
2333
|
+
/* Is the given timeout valid? */
|
2334
|
+
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2335
|
+
/* Wait for the socket to become readable before checking again */
|
2336
|
+
ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout ? &waittime : NULL );
|
2337
|
+
} else {
|
2338
|
+
ret = 0;
|
2339
|
+
}
|
2340
|
+
|
2295
2341
|
|
2296
2342
|
#ifdef _WIN32
|
2297
2343
|
cleanup_crt_fd(&sd_rset, &crt_sd_rset);
|
@@ -2311,7 +2357,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2311
2357
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2312
2358
|
if ( PQconsumeInput(conn) == 0 ){
|
2313
2359
|
rb_fd_term( &sd_rset );
|
2314
|
-
rb_raise(
|
2360
|
+
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2315
2361
|
}
|
2316
2362
|
}
|
2317
2363
|
|
@@ -2325,7 +2371,7 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
|
|
2325
2371
|
static void *
|
2326
2372
|
notify_readable(PGconn *conn)
|
2327
2373
|
{
|
2328
|
-
return (void*)
|
2374
|
+
return (void*)gvl_PQnotifies(conn);
|
2329
2375
|
}
|
2330
2376
|
|
2331
2377
|
/*
|
@@ -2761,7 +2807,7 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
|
|
2761
2807
|
|
2762
2808
|
/*
|
2763
2809
|
* call-seq:
|
2764
|
-
* conn.transaction { |conn| ... } ->
|
2810
|
+
* conn.transaction { |conn| ... } -> result of the block
|
2765
2811
|
*
|
2766
2812
|
* Executes a +BEGIN+ at the start of the block,
|
2767
2813
|
* and a +COMMIT+ at the end of the block, or
|
@@ -2773,13 +2819,14 @@ pgconn_transaction(VALUE self)
|
|
2773
2819
|
PGconn *conn = pg_get_pgconn(self);
|
2774
2820
|
PGresult *result;
|
2775
2821
|
VALUE rb_pgresult;
|
2822
|
+
VALUE block_result = Qnil;
|
2776
2823
|
int status;
|
2777
2824
|
|
2778
2825
|
if (rb_block_given_p()) {
|
2779
2826
|
result = gvl_PQexec(conn, "BEGIN");
|
2780
2827
|
rb_pgresult = pg_new_result(result, self);
|
2781
2828
|
pg_result_check(rb_pgresult);
|
2782
|
-
rb_protect(rb_yield, self, &status);
|
2829
|
+
block_result = rb_protect(rb_yield, self, &status);
|
2783
2830
|
if(status == 0) {
|
2784
2831
|
result = gvl_PQexec(conn, "COMMIT");
|
2785
2832
|
rb_pgresult = pg_new_result(result, self);
|
@@ -2798,7 +2845,7 @@ pgconn_transaction(VALUE self)
|
|
2798
2845
|
/* no block supplied? */
|
2799
2846
|
rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
|
2800
2847
|
}
|
2801
|
-
return
|
2848
|
+
return block_result;
|
2802
2849
|
}
|
2803
2850
|
|
2804
2851
|
|
@@ -2832,6 +2879,9 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
|
2832
2879
|
* double-quotes. */
|
2833
2880
|
char buffer[NAMEDATALEN*2+2];
|
2834
2881
|
unsigned int i=0,j=0;
|
2882
|
+
#ifdef M17N_SUPPORTED
|
2883
|
+
rb_encoding* enc;
|
2884
|
+
#endif
|
2835
2885
|
|
2836
2886
|
UNUSED( self );
|
2837
2887
|
|
@@ -2849,6 +2899,16 @@ pgconn_s_quote_ident(VALUE self, VALUE in_str)
|
|
2849
2899
|
buffer[j++] = '"';
|
2850
2900
|
ret = rb_str_new(buffer,j);
|
2851
2901
|
OBJ_INFECT(ret, in_str);
|
2902
|
+
|
2903
|
+
#ifdef M17N_SUPPORTED
|
2904
|
+
if ( rb_obj_class(self) == rb_cPGconn ) {
|
2905
|
+
enc = pg_conn_enc_get( pg_get_pgconn(self) );
|
2906
|
+
} else {
|
2907
|
+
enc = rb_enc_get(in_str);
|
2908
|
+
}
|
2909
|
+
rb_enc_associate(ret, enc);
|
2910
|
+
#endif
|
2911
|
+
|
2852
2912
|
return ret;
|
2853
2913
|
}
|
2854
2914
|
|