pg 0.15.1-x64-mingw32 → 0.16.0-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -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