pg 1.3.0.rc1-x86-mingw32 → 1.3.0-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
data/ext/pg_connection.c CHANGED
@@ -249,68 +249,13 @@ pgconn_s_allocate( VALUE klass )
249
249
  return self;
250
250
  }
251
251
 
252
-
253
- /*
254
- * Document-method: new
255
- *
256
- * call-seq:
257
- * PG::Connection.new -> conn
258
- * PG::Connection.new(connection_hash) -> conn
259
- * PG::Connection.new(connection_string) -> conn
260
- * PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
261
- *
262
- * Create a connection to the specified server.
263
- *
264
- * +connection_hash+ must be a ruby Hash with connection parameters.
265
- * See the {list of valid parameters}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS] in the PostgreSQL documentation.
266
- *
267
- * There are two accepted formats for +connection_string+: plain <code>keyword = value</code> strings and URIs.
268
- * See the documentation of {connection strings}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING].
269
- *
270
- * The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
271
- * [+host+]
272
- * server hostname
273
- * [+port+]
274
- * server port number
275
- * [+options+]
276
- * backend options
277
- * [+tty+]
278
- * (ignored in all versions of PostgreSQL)
279
- * [+dbname+]
280
- * connecting database name
281
- * [+user+]
282
- * login user name
283
- * [+password+]
284
- * login password
285
- *
286
- * Examples:
287
- *
288
- * # Connect using all defaults
289
- * PG::Connection.new
290
- *
291
- * # As a Hash
292
- * PG::Connection.new( dbname: 'test', port: 5432 )
293
- *
294
- * # As a String
295
- * PG::Connection.new( "dbname=test port=5432" )
296
- *
297
- * # As an Array
298
- * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
299
- *
300
- * # As an URI
301
- * PG::Connection.new( "postgresql://user:pass@pgsql.example.com:5432/testdb?sslmode=require" )
302
- *
303
- * If the Ruby default internal encoding is set (i.e., <code>Encoding.default_internal != nil</code>), the
304
- * connection will have its +client_encoding+ set accordingly.
305
- *
306
- * Raises a PG::Error if the connection fails.
307
- */
308
252
  static VALUE
309
- pgconn_init(int argc, VALUE *argv, VALUE self)
253
+ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
310
254
  {
311
255
  t_pg_connection *this;
312
256
  VALUE conninfo;
313
257
  VALUE error;
258
+ VALUE self = pgconn_s_allocate( klass );
314
259
 
315
260
  this = pg_get_connection( self );
316
261
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
@@ -383,28 +328,8 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
383
328
  return rb_conn;
384
329
  }
385
330
 
386
- /*
387
- * call-seq:
388
- * PG::Connection.ping(connection_hash) -> Integer
389
- * PG::Connection.ping(connection_string) -> Integer
390
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
391
- *
392
- * Check server status.
393
- *
394
- * See PG::Connection.new for a description of the parameters.
395
- *
396
- * Returns one of:
397
- * [+PQPING_OK+]
398
- * server is accepting connections
399
- * [+PQPING_REJECT+]
400
- * server is alive but rejecting connections
401
- * [+PQPING_NO_RESPONSE+]
402
- * could not establish connection
403
- * [+PQPING_NO_ATTEMPT+]
404
- * connection not attempted (bad params)
405
- */
406
331
  static VALUE
407
- pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
332
+ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
408
333
  {
409
334
  PGPing ping;
410
335
  VALUE conninfo;
@@ -453,30 +378,8 @@ pgconn_s_conndefaults(VALUE self)
453
378
 
454
379
 
455
380
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
456
- /*
457
- * call-seq:
458
- * conn.encrypt_password( password, username, algorithm=nil ) -> String
459
- *
460
- * This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
461
- * It is good practice not to send the original cleartext password in such a command, because it might be exposed in command logs, activity displays, and so on.
462
- * Instead, use this function to convert the password to encrypted form before it is sent.
463
- *
464
- * The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
465
- * +algorithm+ specifies the encryption algorithm to use to encrypt the password.
466
- * Currently supported algorithms are +md5+ and +scram-sha-256+ (+on+ and +off+ are also accepted as aliases for +md5+, for compatibility with older server versions).
467
- * Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
468
- * If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
469
- * That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
470
- * If you wish to use the default algorithm for the server but want to avoid blocking, query +password_encryption+ yourself before calling #encrypt_password, and pass that value as the algorithm.
471
- *
472
- * Return value is the encrypted password.
473
- * The caller can assume the string doesn't contain any special characters that would require escaping.
474
- *
475
- * Available since PostgreSQL-10.
476
- * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN].
477
- */
478
381
  static VALUE
479
- pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
382
+ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
480
383
  {
481
384
  char *encrypted = NULL;
482
385
  VALUE rval = Qnil;
@@ -571,6 +474,11 @@ pgconn_connect_poll(VALUE self)
571
474
  {
572
475
  PostgresPollingStatusType status;
573
476
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
477
+
478
+ if ( status == PGRES_POLLING_FAILED ) {
479
+ pgconn_close_socket_io(self);
480
+ }
481
+
574
482
  return INT2FIX((int)status);
575
483
  }
576
484
 
@@ -607,15 +515,8 @@ pgconn_finished_p( VALUE self )
607
515
  }
608
516
 
609
517
 
610
- /*
611
- * call-seq:
612
- * conn.reset()
613
- *
614
- * Resets the backend connection. This method closes the
615
- * backend connection and tries to re-connect.
616
- */
617
518
  static VALUE
618
- pgconn_reset( VALUE self )
519
+ pgconn_sync_reset( VALUE self )
619
520
  {
620
521
  pgconn_close_socket_io( self );
621
522
  gvl_PQreset( pg_get_pgconn(self) );
@@ -654,6 +555,11 @@ pgconn_reset_poll(VALUE self)
654
555
  {
655
556
  PostgresPollingStatusType status;
656
557
  status = gvl_PQresetPoll(pg_get_pgconn(self));
558
+
559
+ if ( status == PGRES_POLLING_FAILED ) {
560
+ pgconn_close_socket_io(self);
561
+ }
562
+
657
563
  return INT2FIX((int)status);
658
564
  }
659
565
 
@@ -779,7 +685,11 @@ pgconn_conninfo( VALUE self )
779
685
  * call-seq:
780
686
  * conn.status()
781
687
  *
782
- * Returns status of connection : CONNECTION_OK or CONNECTION_BAD
688
+ * Returns the status of the connection, which is one:
689
+ * PG::Constants::CONNECTION_OK
690
+ * PG::Constants::CONNECTION_BAD
691
+ *
692
+ * ... and other constants of kind PG::Constants::CONNECTION_*
783
693
  */
784
694
  static VALUE
785
695
  pgconn_status(VALUE self)
@@ -1044,7 +954,7 @@ pgconn_connection_used_password(VALUE self)
1044
954
  /* :TODO: get_ssl */
1045
955
 
1046
956
 
1047
- static VALUE pgconn_exec_params( int, VALUE *, VALUE );
957
+ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
1048
958
 
1049
959
  /*
1050
960
  * call-seq:
@@ -1058,11 +968,11 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
1058
968
  * However #async_exec has two advantages:
1059
969
  *
1060
970
  * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
1061
- * 2. Ruby VM gets notified about IO blocked operations.
1062
- * It can therefore schedule things like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
971
+ * 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
972
+ * So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
1063
973
  */
1064
974
  static VALUE
1065
- pgconn_exec(int argc, VALUE *argv, VALUE self)
975
+ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
1066
976
  {
1067
977
  t_pg_connection *this = pg_get_connection_safe( self );
1068
978
  PGresult *result = NULL;
@@ -1083,7 +993,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
1083
993
  pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
1084
994
 
1085
995
  /* Otherwise, just call #exec_params instead for backward-compatibility */
1086
- return pgconn_exec_params( argc, argv, self );
996
+ return pgconn_sync_exec_params( argc, argv, self );
1087
997
 
1088
998
  }
1089
999
 
@@ -1365,7 +1275,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1365
1275
  * It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
1366
1276
  */
1367
1277
  static VALUE
1368
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1278
+ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1369
1279
  {
1370
1280
  t_pg_connection *this = pg_get_connection_safe( self );
1371
1281
  PGresult *result = NULL;
@@ -1385,7 +1295,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1385
1295
  */
1386
1296
  if ( NIL_P(paramsData.params) ) {
1387
1297
  pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1388
- return pgconn_exec( 1, argv, self );
1298
+ return pgconn_sync_exec( 1, argv, self );
1389
1299
  }
1390
1300
  pgconn_query_assign_typemap( self, &paramsData );
1391
1301
 
@@ -1416,7 +1326,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1416
1326
  * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1417
1327
  */
1418
1328
  static VALUE
1419
- pgconn_prepare(int argc, VALUE *argv, VALUE self)
1329
+ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1420
1330
  {
1421
1331
  t_pg_connection *this = pg_get_connection_safe( self );
1422
1332
  PGresult *result = NULL;
@@ -1465,7 +1375,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1465
1375
  * It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
1466
1376
  */
1467
1377
  static VALUE
1468
- pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1378
+ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1469
1379
  {
1470
1380
  t_pg_connection *this = pg_get_connection_safe( self );
1471
1381
  PGresult *result = NULL;
@@ -1510,7 +1420,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1510
1420
  * It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
1511
1421
  */
1512
1422
  static VALUE
1513
- pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1423
+ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1514
1424
  {
1515
1425
  PGresult *result;
1516
1426
  VALUE rb_pgresult;
@@ -1538,7 +1448,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1538
1448
  * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1539
1449
  */
1540
1450
  static VALUE
1541
- pgconn_describe_portal(self, stmt_name)
1451
+ pgconn_sync_describe_portal(self, stmt_name)
1542
1452
  VALUE self, stmt_name;
1543
1453
  {
1544
1454
  PGresult *result;
@@ -2133,24 +2043,8 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
2133
2043
  }
2134
2044
 
2135
2045
 
2136
- /*
2137
- * call-seq:
2138
- * conn.get_result() -> PG::Result
2139
- * conn.get_result() {|pg_result| block }
2140
- *
2141
- * Blocks waiting for the next result from a call to
2142
- * #send_query (or another asynchronous command), and returns
2143
- * it. Returns +nil+ if no more results are available.
2144
- *
2145
- * Note: call this function repeatedly until it returns +nil+, or else
2146
- * you will not be able to issue further commands.
2147
- *
2148
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
2149
- * and the PG::Result object will automatically be cleared when the block terminates.
2150
- * In this instance, <code>conn.exec</code> returns the value of the block.
2151
- */
2152
2046
  static VALUE
2153
- pgconn_get_result(VALUE self)
2047
+ pgconn_sync_get_result(VALUE self)
2154
2048
  {
2155
2049
  PGconn *conn = pg_get_pgconn(self);
2156
2050
  PGresult *result;
@@ -2183,6 +2077,7 @@ pgconn_consume_input(self)
2183
2077
  PGconn *conn = pg_get_pgconn(self);
2184
2078
  /* returns 0 on error */
2185
2079
  if(PQconsumeInput(conn) == 0) {
2080
+ pgconn_close_socket_io(self);
2186
2081
  error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2187
2082
  rb_iv_set(error, "@connection", self);
2188
2083
  rb_exc_raise(error);
@@ -2195,7 +2090,7 @@ pgconn_consume_input(self)
2195
2090
  * conn.is_busy() -> Boolean
2196
2091
  *
2197
2092
  * Returns +true+ if a command is busy, that is, if
2198
- * PQgetResult would block. Otherwise returns +false+.
2093
+ * #get_result would block. Otherwise returns +false+.
2199
2094
  */
2200
2095
  static VALUE
2201
2096
  pgconn_is_busy(self)
@@ -2204,24 +2099,8 @@ pgconn_is_busy(self)
2204
2099
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2205
2100
  }
2206
2101
 
2207
- /*
2208
- * call-seq:
2209
- * conn.setnonblocking(Boolean) -> nil
2210
- *
2211
- * Sets the nonblocking status of the connection.
2212
- * In the blocking state, calls to #send_query
2213
- * will block until the message is sent to the server,
2214
- * but will not wait for the query results.
2215
- * In the nonblocking state, calls to #send_query
2216
- * will return an error if the socket is not ready for
2217
- * writing.
2218
- * Note: This function does not affect #exec, because
2219
- * that function doesn't return until the server has
2220
- * processed the query and returned the results.
2221
- * Returns +nil+.
2222
- */
2223
2102
  static VALUE
2224
- pgconn_setnonblocking(self, state)
2103
+ pgconn_sync_setnonblocking(self, state)
2225
2104
  VALUE self, state;
2226
2105
  {
2227
2106
  int arg;
@@ -2243,30 +2122,13 @@ pgconn_setnonblocking(self, state)
2243
2122
  }
2244
2123
 
2245
2124
 
2246
- /*
2247
- * call-seq:
2248
- * conn.isnonblocking() -> Boolean
2249
- *
2250
- * Returns +true+ if a command is busy, that is, if
2251
- * PQgetResult would block. Otherwise returns +false+.
2252
- */
2253
2125
  static VALUE
2254
- pgconn_isnonblocking(self)
2126
+ pgconn_sync_isnonblocking(self)
2255
2127
  VALUE self;
2256
2128
  {
2257
2129
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2258
2130
  }
2259
2131
 
2260
- /*
2261
- * call-seq:
2262
- * conn.flush() -> Boolean
2263
- *
2264
- * Attempts to flush any queued output data to the server.
2265
- * Returns +true+ if data is successfully flushed, +false+
2266
- * if not (can only return +false+ if connection is
2267
- * nonblocking.
2268
- * Raises PG::Error if some other failure occurred.
2269
- */
2270
2132
  static VALUE
2271
2133
  pgconn_sync_flush(VALUE self)
2272
2134
  {
@@ -2282,18 +2144,8 @@ pgconn_sync_flush(VALUE self)
2282
2144
  return (ret) ? Qfalse : Qtrue;
2283
2145
  }
2284
2146
 
2285
- /*
2286
- * call-seq:
2287
- * conn.cancel() -> String
2288
- *
2289
- * Requests cancellation of the command currently being
2290
- * processed.
2291
- *
2292
- * Returns +nil+ on success, or a string containing the
2293
- * error message if a failure occurs.
2294
- */
2295
2147
  static VALUE
2296
- pgconn_cancel(VALUE self)
2148
+ pgconn_sync_cancel(VALUE self)
2297
2149
  {
2298
2150
  char errbuf[256];
2299
2151
  PGcancel *cancel;
@@ -2355,18 +2207,128 @@ pgconn_notifies(VALUE self)
2355
2207
  return hash;
2356
2208
  }
2357
2209
 
2210
+ #if defined(_WIN32)
2211
+
2212
+ /* We use a specialized implementation of rb_io_wait() on Windows.
2213
+ * This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
2214
+ */
2215
+
2216
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2217
+ #include <ruby/fiber/scheduler.h>
2218
+ #endif
2219
+
2220
+ typedef enum {
2221
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2222
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2223
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2224
+ } pg_rb_io_event_t;
2225
+
2226
+ int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2227
+
2228
+ static VALUE
2229
+ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
2230
+ rb_io_t *fptr;
2231
+ struct timeval ptimeout;
2232
+
2233
+ struct timeval aborttime={0,0}, currtime, waittime;
2234
+ DWORD timeout_milisec = INFINITE;
2235
+ HANDLE hEvent = WSACreateEvent();
2236
+
2237
+ long rb_events = NUM2UINT(events);
2238
+ long w32_events = 0;
2239
+ DWORD wait_ret;
2240
+
2241
+ GetOpenFile((io), fptr);
2242
+ if( !NIL_P(timeout) ){
2243
+ ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
2244
+ ptimeout.tv_usec = (time_t)(NUM2DBL(timeout) - (double)ptimeout.tv_sec);
2245
+
2246
+ gettimeofday(&currtime, NULL);
2247
+ timeradd(&currtime, &ptimeout, &aborttime);
2248
+ }
2249
+
2250
+ if(rb_events & PG_RUBY_IO_READABLE) {
2251
+ w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2252
+ } else if(rb_events & PG_RUBY_IO_WRITABLE) {
2253
+ w32_events |= FD_WRITE | FD_CONNECT;
2254
+ } else if(rb_events & PG_RUBY_IO_PRIORITY) {
2255
+ w32_events |= FD_OOB;
2256
+ }
2257
+
2258
+ for(;;) {
2259
+ if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
2260
+ WSACloseEvent( hEvent );
2261
+ rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2262
+ }
2263
+
2264
+ if ( !NIL_P(timeout) ) {
2265
+ gettimeofday(&currtime, NULL);
2266
+ timersub(&aborttime, &currtime, &waittime);
2267
+ timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
2268
+ }
2269
+
2270
+ if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2271
+ /* Wait for the socket to become readable before checking again */
2272
+ wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2273
+ } else {
2274
+ wait_ret = WAIT_TIMEOUT;
2275
+ }
2276
+
2277
+ if ( wait_ret == WAIT_TIMEOUT ) {
2278
+ WSACloseEvent( hEvent );
2279
+ return UINT2NUM(0);
2280
+ } else if ( wait_ret == WAIT_OBJECT_0 ) {
2281
+ WSACloseEvent( hEvent );
2282
+ /* The event we were waiting for. */
2283
+ return UINT2NUM(rb_events);
2284
+ } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2285
+ /* This indicates interruption from timer thread, GC, exception
2286
+ * from other threads etc... */
2287
+ rb_thread_check_ints();
2288
+ } else if ( wait_ret == WAIT_FAILED ) {
2289
+ WSACloseEvent( hEvent );
2290
+ rb_raise( rb_eConnectionBad, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
2291
+ } else {
2292
+ WSACloseEvent( hEvent );
2293
+ rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
2294
+ }
2295
+ }
2296
+ }
2297
+
2298
+ static VALUE
2299
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2300
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2301
+ /* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
2302
+ * Fortunatelly ruby-3.1 offers a C-API for it.
2303
+ */
2304
+ VALUE scheduler = rb_fiber_scheduler_current();
2305
+
2306
+ if (!NIL_P(scheduler)) {
2307
+ return rb_io_wait(io, events, timeout);
2308
+ }
2309
+ #endif
2310
+ return pg_rb_thread_io_wait(io, events, timeout);
2311
+ }
2312
+
2313
+ #elif defined(HAVE_RB_IO_WAIT)
2358
2314
 
2359
- #if !defined(HAVE_RB_IO_WAIT)
2315
+ /* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
2316
+ #define pg_rb_io_wait rb_io_wait
2317
+ #define PG_RUBY_IO_READABLE RUBY_IO_READABLE
2318
+ #define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
2319
+ #define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
2320
+
2321
+ #else
2360
2322
  /* For compat with ruby < 3.0 */
2361
2323
 
2362
2324
  typedef enum {
2363
- RUBY_IO_READABLE = RB_WAITFD_IN,
2364
- RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2365
- RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2366
- } rb_io_event_t;
2325
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2326
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2327
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2328
+ } pg_rb_io_event_t;
2367
2329
 
2368
2330
  static VALUE
2369
- rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2331
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2370
2332
  rb_io_t *fptr;
2371
2333
  struct timeval waittime;
2372
2334
  int res;
@@ -2395,8 +2357,10 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2395
2357
  socket_io = pgconn_socket_io(self);
2396
2358
 
2397
2359
  /* Check for connection errors (PQisBusy is true on connection errors) */
2398
- if ( PQconsumeInput(conn) == 0 )
2360
+ if ( PQconsumeInput(conn) == 0 ) {
2361
+ pgconn_close_socket_io(self);
2399
2362
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2363
+ }
2400
2364
 
2401
2365
  if ( ptimeout ) {
2402
2366
  gettimeofday(&currtime, NULL);
@@ -2413,7 +2377,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2413
2377
  /* Is the given timeout valid? */
2414
2378
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2415
2379
  /* Wait for the socket to become readable before checking again */
2416
- ret = rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), wait_timeout);
2380
+ ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2417
2381
  } else {
2418
2382
  ret = Qfalse;
2419
2383
  }
@@ -2425,6 +2389,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2425
2389
 
2426
2390
  /* Check for connection errors (PQisBusy is true on connection errors) */
2427
2391
  if ( PQconsumeInput(conn) == 0 ){
2392
+ pgconn_close_socket_io(self);
2428
2393
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2429
2394
  }
2430
2395
  }
@@ -2432,6 +2397,16 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2432
2397
  return retval;
2433
2398
  }
2434
2399
 
2400
+ /*
2401
+ * call-seq:
2402
+ * conn.flush() -> Boolean
2403
+ *
2404
+ * Attempts to flush any queued output data to the server.
2405
+ * Returns +true+ if data is successfully flushed, +false+
2406
+ * if not (can only return +false+ if connection is
2407
+ * nonblocking.
2408
+ * Raises PG::Error if some other failure occurred.
2409
+ */
2435
2410
  static VALUE
2436
2411
  pgconn_async_flush(VALUE self)
2437
2412
  {
@@ -2439,9 +2414,9 @@ pgconn_async_flush(VALUE self)
2439
2414
  /* wait for the socket to become read- or write-ready */
2440
2415
  int events;
2441
2416
  VALUE socket_io = pgconn_socket_io(self);
2442
- events = RB_NUM2INT(rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
2417
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2443
2418
 
2444
- if (events & RUBY_IO_READABLE)
2419
+ if (events & PG_RUBY_IO_READABLE)
2445
2420
  pgconn_consume_input(self);
2446
2421
  }
2447
2422
  return Qtrue;
@@ -2520,28 +2495,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2520
2495
  }
2521
2496
 
2522
2497
 
2523
- /*
2524
- * call-seq:
2525
- * conn.put_copy_data( buffer [, encoder] ) -> Boolean
2526
- *
2527
- * Transmits _buffer_ as copy data to the server.
2528
- * Returns true if the data was sent, false if it was
2529
- * not sent (false is only possible if the connection
2530
- * is in nonblocking mode, and this command would block).
2531
- *
2532
- * _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
2533
- * This encodes the data fields given as _buffer_ from an Array of Strings to
2534
- * PostgreSQL's COPY text format inclusive proper escaping. Optionally
2535
- * the encoder can type cast the fields from various Ruby types in one step,
2536
- * if PG::TextEncoder::CopyRow#type_map is set accordingly.
2537
- *
2538
- * Raises an exception if an error occurs.
2539
- *
2540
- * See also #copy_data.
2541
- *
2542
- */
2543
2498
  static VALUE
2544
- pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2499
+ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2545
2500
  {
2546
2501
  int ret;
2547
2502
  int len;
@@ -2596,22 +2551,8 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2596
2551
  return (ret) ? Qtrue : Qfalse;
2597
2552
  }
2598
2553
 
2599
- /*
2600
- * call-seq:
2601
- * conn.put_copy_end( [ error_message ] ) -> Boolean
2602
- *
2603
- * Sends end-of-data indication to the server.
2604
- *
2605
- * _error_message_ is an optional parameter, and if set,
2606
- * forces the COPY command to fail with the string
2607
- * _error_message_.
2608
- *
2609
- * Returns true if the end-of-data was sent, *false* if it was
2610
- * not sent (*false* is only possible if the connection
2611
- * is in nonblocking mode, and this command would block).
2612
- */
2613
2554
  static VALUE
2614
- pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2555
+ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2615
2556
  {
2616
2557
  VALUE str;
2617
2558
  VALUE error;
@@ -2633,27 +2574,8 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2633
2574
  return (ret) ? Qtrue : Qfalse;
2634
2575
  }
2635
2576
 
2636
- /*
2637
- * call-seq:
2638
- * conn.get_copy_data( [ nonblock = false [, decoder = nil ]] ) -> Object
2639
- *
2640
- * Return one row of data, +nil+
2641
- * if the copy is done, or +false+ if the call would
2642
- * block (only possible if _nonblock_ is true).
2643
- *
2644
- * If _decoder_ is not set or +nil+, data is returned as binary string.
2645
- *
2646
- * If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
2647
- * PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
2648
- * COPY text format to an Array of Strings.
2649
- * Optionally the decoder can type cast the single fields to various Ruby types in one step,
2650
- * if PG::TextDecoder::CopyRow#type_map is set accordingly.
2651
- *
2652
- * See also #copy_data.
2653
- *
2654
- */
2655
2577
  static VALUE
2656
- pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2578
+ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2657
2579
  {
2658
2580
  VALUE async_in;
2659
2581
  VALUE error;
@@ -2978,7 +2900,7 @@ pgconn_get_client_encoding(VALUE self)
2978
2900
  * It's not recommended to use explicit sync or async variants but #set_client_encoding instead, unless you have a good reason to do so.
2979
2901
  */
2980
2902
  static VALUE
2981
- pgconn_set_client_encoding(VALUE self, VALUE str)
2903
+ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2982
2904
  {
2983
2905
  PGconn *conn = pg_get_pgconn( self );
2984
2906
 
@@ -3099,7 +3021,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3099
3021
  * It's not recommended to use explicit sync or async variants but #get_last_result instead, unless you have a good reason to do so.
3100
3022
  */
3101
3023
  static VALUE
3102
- pgconn_get_last_result(VALUE self)
3024
+ pgconn_sync_get_last_result(VALUE self)
3103
3025
  {
3104
3026
  PGconn *conn = pg_get_pgconn(self);
3105
3027
  VALUE rb_pgresult = Qnil;
@@ -3201,12 +3123,14 @@ pgconn_discard_results(VALUE self)
3201
3123
  int status;
3202
3124
 
3203
3125
  /* pgconn_block() raises an exception in case of errors.
3204
- * To avoid this call rb_io_wait() and PQconsumeInput() without rb_raise().
3126
+ * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3205
3127
  */
3206
3128
  while( gvl_PQisBusy(conn) ){
3207
- rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
3208
- if ( PQconsumeInput(conn) == 0 )
3129
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3130
+ if ( PQconsumeInput(conn) == 0 ) {
3131
+ pgconn_close_socket_io(self);
3209
3132
  return Qfalse;
3133
+ }
3210
3134
  }
3211
3135
 
3212
3136
  cur = gvl_PQgetResult(conn);
@@ -3223,9 +3147,11 @@ pgconn_discard_results(VALUE self)
3223
3147
  int st = gvl_PQgetCopyData(conn, &buffer, 1);
3224
3148
  if( st == 0 ) {
3225
3149
  /* would block -> wait for readable data */
3226
- rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
3227
- if ( PQconsumeInput(conn) == 0 )
3150
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3151
+ if ( PQconsumeInput(conn) == 0 ) {
3152
+ pgconn_close_socket_io(self);
3228
3153
  return Qfalse;
3154
+ }
3229
3155
  } else if( st > 0 ) {
3230
3156
  /* some data retrieved -> discard it */
3231
3157
  PQfreemem(buffer);
@@ -3260,6 +3186,7 @@ pgconn_discard_results(VALUE self)
3260
3186
  * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3261
3187
  * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3262
3188
  * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3189
+ * Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
3263
3190
  * Both methods ensure that other threads can process while waiting for the server to
3264
3191
  * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3265
3192
  * This is most notably visible by a delayed reaction to Control+C.
@@ -4037,11 +3964,11 @@ static VALUE
4037
3964
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
4038
3965
  {
4039
3966
  if (NIL_P(enc)) {
4040
- pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3967
+ pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
4041
3968
  return enc;
4042
3969
  }
4043
3970
  else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
4044
- pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3971
+ pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
4045
3972
  return enc;
4046
3973
  }
4047
3974
  else {
@@ -4405,10 +4332,6 @@ init_pg_connection()
4405
4332
  /****** PG::Connection CLASS METHODS ******/
4406
4333
  rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
4407
4334
 
4408
- SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
4409
- SINGLETON_ALIAS(rb_cPGconn, "open", "new");
4410
- SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
4411
- SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
4412
4335
  rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4413
4336
  SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
4414
4337
  rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
@@ -4417,14 +4340,14 @@ init_pg_connection()
4417
4340
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4418
4341
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4419
4342
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4420
- rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
4343
+ rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4344
+ rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4421
4345
 
4422
4346
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
4423
- rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
4424
4347
  rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
4425
4348
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
4426
4349
  rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
4427
- rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
4350
+ rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
4428
4351
  rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
4429
4352
  rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
4430
4353
  rb_define_alias(rb_cPGconn, "close", "finish");
@@ -4453,12 +4376,12 @@ init_pg_connection()
4453
4376
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
4454
4377
 
4455
4378
  /****** PG::Connection INSTANCE METHODS: Command Execution ******/
4456
- rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
4457
- rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
4458
- rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
4459
- rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
4460
- rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
4461
- rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
4379
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
4380
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
4381
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
4382
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4383
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4384
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4462
4385
 
4463
4386
  rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4464
4387
  rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
@@ -4491,26 +4414,26 @@ init_pg_connection()
4491
4414
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
4492
4415
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
4493
4416
  rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
4494
- rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
4417
+ rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
4495
4418
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4496
4419
  rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
4497
- rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
4498
- rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
4499
- rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
4420
+ rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
4421
+ rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
4500
4422
  rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
4501
- rb_define_method(rb_cPGconn, "async_flush", pgconn_async_flush, 0);
4423
+ rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
4424
+ rb_define_alias(rb_cPGconn, "async_flush", "flush");
4502
4425
  rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4503
4426
 
4504
4427
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4505
- rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
4428
+ rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4506
4429
 
4507
4430
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4508
4431
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
4509
4432
 
4510
4433
  /****** PG::Connection INSTANCE METHODS: COPY ******/
4511
- rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, -1);
4512
- rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
4513
- rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
4434
+ rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
4435
+ rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
4436
+ rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
4514
4437
 
4515
4438
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4516
4439
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
@@ -4526,18 +4449,20 @@ init_pg_connection()
4526
4449
 
4527
4450
  /****** PG::Connection INSTANCE METHODS: Other ******/
4528
4451
  rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
4529
- rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_set_client_encoding, 1);
4530
- rb_define_method(rb_cPGconn, "async_set_client_encoding", pgconn_async_set_client_encoding, 1);
4531
- rb_define_alias(rb_cPGconn, "async_client_encoding=", "async_set_client_encoding");
4452
+ rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
4453
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
4454
+ rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
4455
+ rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
4532
4456
  rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
4533
4457
  rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
4534
4458
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
4535
4459
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
4536
4460
  rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4537
- rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_get_last_result, 0);
4538
- rb_define_method(rb_cPGconn, "async_get_last_result", pgconn_async_get_last_result, 0);
4461
+ rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4462
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4463
+ rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4539
4464
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
4540
- rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
4465
+ rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4541
4466
  #endif
4542
4467
 
4543
4468
  #ifdef HAVE_PQSSLATTRIBUTE