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.
@@ -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
- $CPPFLAGS << " -I%s" % [ `"#{pgconfig}" --includedir`.chomp ]
35
-
32
+ incdir = `"#{pgconfig}" --includedir`.chomp
36
33
  libdir = `"#{pgconfig}" --libdir`.chomp
37
- $LDFLAGS << " -L%s -Wl,-rpath,%s" % [ libdir, libdir ]
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'
@@ -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
+ }
@@ -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, &params, RUBY_UBF_IO, 0); \
64
+ rb_thread_call_without_gvl(gvl_##name##_skeleton, &params, 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(PQexec, GVL_TYPE_NONVOID, PGresult *, const char *, command) \
155
- function(PQexecParams, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
156
- function(PQexecPrepared, GVL_TYPE_NONVOID, PGresult *, int, resultFormat) \
157
- function(PQprepare, GVL_TYPE_NONVOID, PGresult *, const Oid *, paramTypes) \
158
- function(PQdescribePrepared, GVL_TYPE_NONVOID, PGresult *, const char *, stmtName) \
159
- function(PQdescribePortal, GVL_TYPE_NONVOID, PGresult *, const char *, portalName) \
160
- function(PQgetResult, GVL_TYPE_NONVOID, PGresult *, PGconn *, conn) \
161
- function(PQputCopyData, GVL_TYPE_NONVOID, int, int, nbytes) \
162
- function(PQputCopyEnd, GVL_TYPE_NONVOID, int, const char *, errormsg) \
163
- function(PQgetCopyData, GVL_TYPE_NONVOID, int, int, async) \
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, GVL_TYPE_VOID, void, const char *, message) \
181
- function(notice_receiver_proxy, GVL_TYPE_VOID, void, const PGresult *, result) \
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
 
@@ -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( rb_ePGerror, "connection is closed" );
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(rb_ePGerror, "Could not unwrap win32 socket handle");
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
- return Data_Wrap_Struct( klass, NULL, pgconn_gc_free, NULL );
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 = PQconnectdb(StringValuePtr(conninfo));
189
+ conn = gvl_PQconnectdb(StringValuePtr(conninfo));
186
190
 
187
191
  if(conn == NULL)
188
- rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
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(rb_ePGerror, PQerrorMessage(conn));
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 = PQconnectStart( StringValuePtr(conninfo) );
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(rb_ePGerror, PQerrorMessage(conn));
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 = PQconnectPoll(pg_get_pgconn(self));
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
- PQreset( pg_get_pgconn(self) );
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(PQresetStart(pg_get_pgconn(self)) == 0)
482
- rb_raise(rb_ePGerror, "reset has failed");
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 = PQresetPoll(pg_get_pgconn(self));
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(rb_ePGerror, "Can't get socket descriptor");
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(rb_ePGerror, "Can't get socket descriptor");
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(rb_ePGerror, PQerrorMessage(conn));
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(rb_ePGerror, PQerrorMessage(conn));
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(rb_ePGerror, PQerrorMessage(conn));
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(rb_ePGerror, PQerrorMessage(conn));
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(rb_ePGerror, PQerrorMessage(conn));
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(rb_ePGerror, PQerrorMessage(conn));
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(rb_ePGerror, PQerrorMessage(conn));
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 = PQnotifies(conn);
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
- rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
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( rb_ePGerror, "%s", PQerrorMessage(conn) );
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( rb_ePGerror, "WSAEventSelect socket error: %d", WSAGetLastError() );
2241
+ rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2225
2242
  }
2226
2243
 
2227
- wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
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( rb_ePGerror, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
2269
+ rb_raise( rb_eConnectionBad, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
2241
2270
  } else {
2242
2271
  WSACloseEvent( hEvent );
2243
- rb_raise( rb_ePGerror, "Wait on socket abandoned (WaitForMultipleObjects)" );
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( rb_ePGerror, "%s", PQerrorMessage(conn) );
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
- rb_bug( "PQsocket(conn): couldn't fetch the connection's socket!" );
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( rb_ePGerror, "%s", PQerrorMessage(conn) );
2307
+ rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2308
+
2309
+ rb_fd_init( &sd_rset );
2278
2310
 
2279
- rb_fd_init( &sd_rset );
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
- /* Wait for the socket to become readable before checking again */
2294
- ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout );
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( rb_ePGerror, "%s", PQerrorMessage(conn) );
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*)PQnotifies(conn);
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| ... } -> nil
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 Qnil;
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