pg 1.2.1-x64-mingw32 → 1.3.0.rc2-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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +85 -0
  6. data/.github/workflows/source-gem.yml +130 -0
  7. data/.gitignore +13 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/Gemfile +14 -0
  15. data/History.rdoc +93 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +8 -7
  18. data/Rakefile +31 -140
  19. data/Rakefile.cross +55 -56
  20. data/certs/ged.pem +24 -0
  21. data/ext/errorcodes.def +8 -0
  22. data/ext/errorcodes.txt +3 -1
  23. data/ext/extconf.rb +90 -19
  24. data/ext/gvl_wrappers.c +4 -0
  25. data/ext/gvl_wrappers.h +23 -0
  26. data/ext/pg.c +59 -4
  27. data/ext/pg.h +18 -0
  28. data/ext/pg_coder.c +90 -24
  29. data/ext/pg_connection.c +606 -533
  30. data/ext/pg_copy_coder.c +45 -15
  31. data/ext/pg_record_coder.c +38 -9
  32. data/ext/pg_result.c +61 -31
  33. data/ext/pg_text_decoder.c +1 -1
  34. data/ext/pg_text_encoder.c +6 -6
  35. data/ext/pg_tuple.c +47 -21
  36. data/ext/pg_type_map.c +41 -8
  37. data/ext/pg_type_map_all_strings.c +14 -1
  38. data/ext/pg_type_map_by_class.c +50 -21
  39. data/ext/pg_type_map_by_column.c +64 -28
  40. data/ext/pg_type_map_by_mri_type.c +47 -18
  41. data/ext/pg_type_map_by_oid.c +52 -23
  42. data/ext/pg_type_map_in_ruby.c +50 -19
  43. data/ext/pg_util.c +2 -2
  44. data/lib/2.5/pg_ext.so +0 -0
  45. data/lib/2.6/pg_ext.so +0 -0
  46. data/lib/2.7/pg_ext.so +0 -0
  47. data/lib/3.0/pg_ext.so +0 -0
  48. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  49. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  50. data/lib/pg/basic_type_map_for_results.rb +81 -0
  51. data/lib/pg/basic_type_registry.rb +296 -0
  52. data/lib/pg/coder.rb +1 -1
  53. data/lib/pg/connection.rb +579 -57
  54. data/lib/pg/version.rb +4 -0
  55. data/lib/pg.rb +38 -24
  56. data/lib/x64-mingw32/libpq.dll +0 -0
  57. data/misc/openssl-pg-segfault.rb +31 -0
  58. data/misc/postgres/History.txt +9 -0
  59. data/misc/postgres/Manifest.txt +5 -0
  60. data/misc/postgres/README.txt +21 -0
  61. data/misc/postgres/Rakefile +21 -0
  62. data/misc/postgres/lib/postgres.rb +16 -0
  63. data/misc/ruby-pg/History.txt +9 -0
  64. data/misc/ruby-pg/Manifest.txt +5 -0
  65. data/misc/ruby-pg/README.txt +21 -0
  66. data/misc/ruby-pg/Rakefile +21 -0
  67. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  68. data/pg.gemspec +32 -0
  69. data/sample/array_insert.rb +20 -0
  70. data/sample/async_api.rb +106 -0
  71. data/sample/async_copyto.rb +39 -0
  72. data/sample/async_mixed.rb +56 -0
  73. data/sample/check_conn.rb +21 -0
  74. data/sample/copydata.rb +71 -0
  75. data/sample/copyfrom.rb +81 -0
  76. data/sample/copyto.rb +19 -0
  77. data/sample/cursor.rb +21 -0
  78. data/sample/disk_usage_report.rb +177 -0
  79. data/sample/issue-119.rb +94 -0
  80. data/sample/losample.rb +69 -0
  81. data/sample/minimal-testcase.rb +17 -0
  82. data/sample/notify_wait.rb +72 -0
  83. data/sample/pg_statistics.rb +285 -0
  84. data/sample/replication_monitor.rb +222 -0
  85. data/sample/test_binary_values.rb +33 -0
  86. data/sample/wal_shipper.rb +434 -0
  87. data/sample/warehouse_partitions.rb +311 -0
  88. data.tar.gz.sig +0 -0
  89. metadata +94 -235
  90. metadata.gz.sig +0 -0
  91. data/ChangeLog +0 -0
  92. data/lib/2.2/pg_ext.so +0 -0
  93. data/lib/2.3/pg_ext.so +0 -0
  94. data/lib/2.4/pg_ext.so +0 -0
  95. data/lib/libpq.dll +0 -0
  96. data/lib/pg/basic_type_mapping.rb +0 -522
  97. data/spec/data/expected_trace.out +0 -26
  98. data/spec/data/random_binary_data +0 -0
  99. data/spec/helpers.rb +0 -382
  100. data/spec/pg/basic_type_mapping_spec.rb +0 -645
  101. data/spec/pg/connection_spec.rb +0 -1911
  102. data/spec/pg/connection_sync_spec.rb +0 -41
  103. data/spec/pg/result_spec.rb +0 -681
  104. data/spec/pg/tuple_spec.rb +0 -333
  105. data/spec/pg/type_map_by_class_spec.rb +0 -138
  106. data/spec/pg/type_map_by_column_spec.rb +0 -226
  107. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  108. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  109. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  110. data/spec/pg/type_map_spec.rb +0 -22
  111. data/spec/pg/type_spec.rb +0 -1123
  112. data/spec/pg_spec.rb +0 -50
data/ext/pg_connection.c CHANGED
@@ -12,6 +12,7 @@
12
12
 
13
13
  VALUE rb_cPGconn;
14
14
  static ID s_id_encode;
15
+ static ID s_id_autoclose_set;
15
16
  static VALUE sym_type, sym_format, sym_value;
16
17
  static VALUE sym_symbol, sym_string, sym_static_symbol;
17
18
 
@@ -20,7 +21,9 @@ static PQnoticeProcessor default_notice_processor = NULL;
20
21
 
21
22
  static VALUE pgconn_finish( VALUE );
22
23
  static VALUE pgconn_set_default_encoding( VALUE self );
24
+ static VALUE pgconn_wait_for_flush( VALUE self );
23
25
  static void pgconn_set_internal_encoding_index( VALUE );
26
+ static const rb_data_type_t pg_connection_type;
24
27
 
25
28
  /*
26
29
  * Global functions
@@ -33,7 +36,7 @@ t_pg_connection *
33
36
  pg_get_connection( VALUE self )
34
37
  {
35
38
  t_pg_connection *this;
36
- Data_Get_Struct( self, t_pg_connection, this);
39
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
37
40
 
38
41
  return this;
39
42
  }
@@ -46,7 +49,7 @@ static t_pg_connection *
46
49
  pg_get_connection_safe( VALUE self )
47
50
  {
48
51
  t_pg_connection *this;
49
- Data_Get_Struct( self, t_pg_connection, this);
52
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
50
53
 
51
54
  if ( !this->pgconn )
52
55
  rb_raise( rb_eConnectionBad, "connection is closed" );
@@ -65,7 +68,7 @@ PGconn *
65
68
  pg_get_pgconn( VALUE self )
66
69
  {
67
70
  t_pg_connection *this;
68
- Data_Get_Struct( self, t_pg_connection, this);
71
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
69
72
 
70
73
  if ( !this->pgconn )
71
74
  rb_raise( rb_eConnectionBad, "connection is closed" );
@@ -145,16 +148,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
145
148
  * GC Mark function
146
149
  */
147
150
  static void
148
- pgconn_gc_mark( t_pg_connection *this )
151
+ pgconn_gc_mark( void *_this )
149
152
  {
150
- rb_gc_mark( this->socket_io );
151
- rb_gc_mark( this->notice_receiver );
152
- rb_gc_mark( this->notice_processor );
153
- rb_gc_mark( this->type_map_for_queries );
154
- rb_gc_mark( this->type_map_for_results );
155
- rb_gc_mark( this->trace_stream );
156
- rb_gc_mark( this->encoder_for_put_copy_data );
157
- rb_gc_mark( this->decoder_for_get_copy_data );
153
+ t_pg_connection *this = (t_pg_connection *)_this;
154
+ rb_gc_mark_movable( this->socket_io );
155
+ rb_gc_mark_movable( this->notice_receiver );
156
+ rb_gc_mark_movable( this->notice_processor );
157
+ rb_gc_mark_movable( this->type_map_for_queries );
158
+ rb_gc_mark_movable( this->type_map_for_results );
159
+ rb_gc_mark_movable( this->trace_stream );
160
+ rb_gc_mark_movable( this->encoder_for_put_copy_data );
161
+ rb_gc_mark_movable( this->decoder_for_get_copy_data );
162
+ }
163
+
164
+ static void
165
+ pgconn_gc_compact( void *_this )
166
+ {
167
+ t_pg_connection *this = (t_pg_connection *)_this;
168
+ pg_gc_location( this->socket_io );
169
+ pg_gc_location( this->notice_receiver );
170
+ pg_gc_location( this->notice_processor );
171
+ pg_gc_location( this->type_map_for_queries );
172
+ pg_gc_location( this->type_map_for_results );
173
+ pg_gc_location( this->trace_stream );
174
+ pg_gc_location( this->encoder_for_put_copy_data );
175
+ pg_gc_location( this->decoder_for_get_copy_data );
158
176
  }
159
177
 
160
178
 
@@ -162,11 +180,15 @@ pgconn_gc_mark( t_pg_connection *this )
162
180
  * GC Free function
163
181
  */
164
182
  static void
165
- pgconn_gc_free( t_pg_connection *this )
183
+ pgconn_gc_free( void *_this )
166
184
  {
185
+ t_pg_connection *this = (t_pg_connection *)_this;
167
186
  #if defined(_WIN32)
168
- if ( RTEST(this->socket_io) )
169
- rb_w32_unwrap_io_handle( this->ruby_sd );
187
+ if ( RTEST(this->socket_io) ) {
188
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
189
+ rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
190
+ }
191
+ }
170
192
  #endif
171
193
  if (this->pgconn != NULL)
172
194
  PQfinish( this->pgconn );
@@ -174,6 +196,29 @@ pgconn_gc_free( t_pg_connection *this )
174
196
  xfree(this);
175
197
  }
176
198
 
199
+ /*
200
+ * Object Size function
201
+ */
202
+ static size_t
203
+ pgconn_memsize( const void *_this )
204
+ {
205
+ const t_pg_connection *this = (const t_pg_connection *)_this;
206
+ return sizeof(*this);
207
+ }
208
+
209
+ static const rb_data_type_t pg_connection_type = {
210
+ "PG::Connection",
211
+ {
212
+ pgconn_gc_mark,
213
+ pgconn_gc_free,
214
+ pgconn_memsize,
215
+ pg_compact_callback(pgconn_gc_compact),
216
+ },
217
+ 0,
218
+ 0,
219
+ 0,
220
+ };
221
+
177
222
 
178
223
  /**************************************************************************
179
224
  * Class Methods
@@ -189,7 +234,7 @@ static VALUE
189
234
  pgconn_s_allocate( VALUE klass )
190
235
  {
191
236
  t_pg_connection *this;
192
- VALUE self = Data_Make_Struct( klass, t_pg_connection, pgconn_gc_mark, pgconn_gc_free, this );
237
+ VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
193
238
 
194
239
  this->pgconn = NULL;
195
240
  this->socket_io = Qnil;
@@ -204,65 +249,13 @@ pgconn_s_allocate( VALUE klass )
204
249
  return self;
205
250
  }
206
251
 
207
-
208
- /*
209
- * Document-method: new
210
- *
211
- * call-seq:
212
- * PG::Connection.new -> conn
213
- * PG::Connection.new(connection_hash) -> conn
214
- * PG::Connection.new(connection_string) -> conn
215
- * PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
216
- *
217
- * Create a connection to the specified server.
218
- *
219
- * +connection_hash+ must be a ruby Hash with connection parameters.
220
- * See the {list of valid parameters}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PARAMKEYWORDS] in the PostgreSQL documentation.
221
- *
222
- * There are two accepted formats for +connection_string+: plain <code>keyword = value</code> strings and URIs.
223
- * See the documentation of {connection strings}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING].
224
- *
225
- * The positional parameter form has the same functionality except that the missing parameters will always take on default values. The parameters are:
226
- * [+host+]
227
- * server hostname
228
- * [+port+]
229
- * server port number
230
- * [+options+]
231
- * backend options
232
- * [+tty+]
233
- * (ignored in newer versions of PostgreSQL)
234
- * [+dbname+]
235
- * connecting database name
236
- * [+user+]
237
- * login user name
238
- * [+password+]
239
- * login password
240
- *
241
- * Examples:
242
- *
243
- * # Connect using all defaults
244
- * PG::Connection.new
245
- *
246
- * # As a Hash
247
- * PG::Connection.new( :dbname => 'test', :port => 5432 )
248
- *
249
- * # As a String
250
- * PG::Connection.new( "dbname=test port=5432" )
251
- *
252
- * # As an Array
253
- * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
254
- *
255
- * If the Ruby default internal encoding is set (i.e., <code>Encoding.default_internal != nil</code>), the
256
- * connection will have its +client_encoding+ set accordingly.
257
- *
258
- * Raises a PG::Error if the connection fails.
259
- */
260
252
  static VALUE
261
- pgconn_init(int argc, VALUE *argv, VALUE self)
253
+ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
262
254
  {
263
255
  t_pg_connection *this;
264
256
  VALUE conninfo;
265
257
  VALUE error;
258
+ VALUE self = pgconn_s_allocate( klass );
266
259
 
267
260
  this = pg_get_connection( self );
268
261
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
@@ -335,34 +328,14 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
335
328
  return rb_conn;
336
329
  }
337
330
 
338
- /*
339
- * call-seq:
340
- * PG::Connection.ping(connection_hash) -> Integer
341
- * PG::Connection.ping(connection_string) -> Integer
342
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
343
- *
344
- * Check server status.
345
- *
346
- * See PG::Connection.new for a description of the parameters.
347
- *
348
- * Returns one of:
349
- * [+PQPING_OK+]
350
- * server is accepting connections
351
- * [+PQPING_REJECT+]
352
- * server is alive but rejecting connections
353
- * [+PQPING_NO_RESPONSE+]
354
- * could not establish connection
355
- * [+PQPING_NO_ATTEMPT+]
356
- * connection not attempted (bad params)
357
- */
358
331
  static VALUE
359
- pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
332
+ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
360
333
  {
361
334
  PGPing ping;
362
335
  VALUE conninfo;
363
336
 
364
337
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
365
- ping = PQping( StringValueCStr(conninfo) );
338
+ ping = gvl_PQping( StringValueCStr(conninfo) );
366
339
 
367
340
  return INT2FIX((int)ping);
368
341
  }
@@ -405,30 +378,8 @@ pgconn_s_conndefaults(VALUE self)
405
378
 
406
379
 
407
380
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
408
- /*
409
- * call-seq:
410
- * conn.encrypt_password( password, username, algorithm=nil ) -> String
411
- *
412
- * This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
413
- * 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.
414
- * Instead, use this function to convert the password to encrypted form before it is sent.
415
- *
416
- * The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
417
- * +algorithm+ specifies the encryption algorithm to use to encrypt the password.
418
- * 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).
419
- * Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
420
- * If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
421
- * That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
422
- * 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.
423
- *
424
- * Return value is the encrypted password.
425
- * The caller can assume the string doesn't contain any special characters that would require escaping.
426
- *
427
- * Available since PostgreSQL-10.
428
- * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-misc.html#LIBPQ-PQENCRYPTPASSWORDCONN].
429
- */
430
381
  static VALUE
431
- pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
382
+ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
432
383
  {
433
384
  char *encrypted = NULL;
434
385
  VALUE rval = Qnil;
@@ -523,6 +474,11 @@ pgconn_connect_poll(VALUE self)
523
474
  {
524
475
  PostgresPollingStatusType status;
525
476
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
477
+
478
+ if ( status == PGRES_POLLING_FAILED ) {
479
+ pgconn_close_socket_io(self);
480
+ }
481
+
526
482
  return INT2FIX((int)status);
527
483
  }
528
484
 
@@ -559,15 +515,8 @@ pgconn_finished_p( VALUE self )
559
515
  }
560
516
 
561
517
 
562
- /*
563
- * call-seq:
564
- * conn.reset()
565
- *
566
- * Resets the backend connection. This method closes the
567
- * backend connection and tries to re-connect.
568
- */
569
518
  static VALUE
570
- pgconn_reset( VALUE self )
519
+ pgconn_sync_reset( VALUE self )
571
520
  {
572
521
  pgconn_close_socket_io( self );
573
522
  gvl_PQreset( pg_get_pgconn(self) );
@@ -606,6 +555,11 @@ pgconn_reset_poll(VALUE self)
606
555
  {
607
556
  PostgresPollingStatusType status;
608
557
  status = gvl_PQresetPoll(pg_get_pgconn(self));
558
+
559
+ if ( status == PGRES_POLLING_FAILED ) {
560
+ pgconn_close_socket_io(self);
561
+ }
562
+
609
563
  return INT2FIX((int)status);
610
564
  }
611
565
 
@@ -676,21 +630,19 @@ static VALUE
676
630
  pgconn_port(VALUE self)
677
631
  {
678
632
  char* port = PQport(pg_get_pgconn(self));
679
- return INT2NUM(atol(port));
633
+ return INT2NUM(atoi(port));
680
634
  }
681
635
 
682
636
  /*
683
637
  * call-seq:
684
638
  * conn.tty()
685
639
  *
686
- * Returns the connected pgtty. (Obsolete)
640
+ * Obsolete function.
687
641
  */
688
642
  static VALUE
689
643
  pgconn_tty(VALUE self)
690
644
  {
691
- char *tty = PQtty(pg_get_pgconn(self));
692
- if (!tty) return Qnil;
693
- return rb_str_new2(tty);
645
+ return rb_str_new2("");
694
646
  }
695
647
 
696
648
  /*
@@ -708,7 +660,6 @@ pgconn_options(VALUE self)
708
660
  }
709
661
 
710
662
 
711
- #ifdef HAVE_PQCONNINFO
712
663
  /*
713
664
  * call-seq:
714
665
  * conn.conninfo -> hash
@@ -728,14 +679,17 @@ pgconn_conninfo( VALUE self )
728
679
 
729
680
  return array;
730
681
  }
731
- #endif
732
682
 
733
683
 
734
684
  /*
735
685
  * call-seq:
736
686
  * conn.status()
737
687
  *
738
- * 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_*
739
693
  */
740
694
  static VALUE
741
695
  pgconn_status(VALUE self)
@@ -823,7 +777,10 @@ pgconn_server_version(VALUE self)
823
777
  * call-seq:
824
778
  * conn.error_message -> String
825
779
  *
826
- * Returns the error message about connection.
780
+ * Returns the error message most recently generated by an operation on the connection.
781
+ *
782
+ * Nearly all libpq functions will set a message for conn.error_message if they fail.
783
+ * Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
827
784
  */
828
785
  static VALUE
829
786
  pgconn_error_message(VALUE self)
@@ -878,8 +835,8 @@ pgconn_socket_io(VALUE self)
878
835
  {
879
836
  int sd;
880
837
  int ruby_sd;
881
- ID id_autoclose = rb_intern("autoclose=");
882
838
  t_pg_connection *this = pg_get_connection_safe( self );
839
+ VALUE cSocket;
883
840
  VALUE socket_io = this->socket_io;
884
841
 
885
842
  if ( !RTEST(socket_io) ) {
@@ -888,15 +845,19 @@ pgconn_socket_io(VALUE self)
888
845
 
889
846
  #ifdef _WIN32
890
847
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
848
+ if( ruby_sd == -1 ){
849
+ rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
850
+ }
891
851
  this->ruby_sd = ruby_sd;
892
852
  #else
893
853
  ruby_sd = sd;
894
854
  #endif
895
855
 
896
- socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
856
+ cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
857
+ socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
897
858
 
898
859
  /* Disable autoclose feature */
899
- rb_funcall( socket_io, id_autoclose, 1, Qfalse );
860
+ rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
900
861
 
901
862
  this->socket_io = socket_io;
902
863
  }
@@ -918,6 +879,51 @@ pgconn_backend_pid(VALUE self)
918
879
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
919
880
  }
920
881
 
882
+ typedef struct
883
+ {
884
+ struct sockaddr_storage addr;
885
+ socklen_t salen;
886
+ } SockAddr;
887
+
888
+ /* Copy of struct pg_cancel from libpq-int.h
889
+ *
890
+ * See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
891
+ */
892
+ struct pg_cancel
893
+ {
894
+ SockAddr raddr; /* Remote address */
895
+ int be_pid; /* PID of backend --- needed for cancels */
896
+ int be_key; /* key of backend --- needed for cancels */
897
+ };
898
+
899
+ /*
900
+ * call-seq:
901
+ * conn.backend_key() -> Integer
902
+ *
903
+ * Returns the key of the backend server process for this connection.
904
+ * This key can be used to cancel queries on the server.
905
+ */
906
+ static VALUE
907
+ pgconn_backend_key(VALUE self)
908
+ {
909
+ int be_key;
910
+ struct pg_cancel *cancel;
911
+ PGconn *conn = pg_get_pgconn(self);
912
+
913
+ cancel = (struct pg_cancel*)PQgetCancel(conn);
914
+ if(cancel == NULL)
915
+ rb_raise(rb_ePGerror,"Invalid connection!");
916
+
917
+ if( cancel->be_pid != PQbackendPID(conn) )
918
+ rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
919
+
920
+ be_key = cancel->be_key;
921
+
922
+ PQfreeCancel(cancel);
923
+
924
+ return INT2NUM(be_key);
925
+ }
926
+
921
927
  /*
922
928
  * call-seq:
923
929
  * conn.connection_needs_password() -> Boolean
@@ -948,7 +954,7 @@ pgconn_connection_used_password(VALUE self)
948
954
  /* :TODO: get_ssl */
949
955
 
950
956
 
951
- static VALUE pgconn_exec_params( int, VALUE *, VALUE );
957
+ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
952
958
 
953
959
  /*
954
960
  * call-seq:
@@ -966,7 +972,7 @@ static VALUE pgconn_exec_params( int, VALUE *, VALUE );
966
972
  * It can therefore schedule things like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
967
973
  */
968
974
  static VALUE
969
- pgconn_exec(int argc, VALUE *argv, VALUE self)
975
+ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
970
976
  {
971
977
  t_pg_connection *this = pg_get_connection_safe( self );
972
978
  PGresult *result = NULL;
@@ -987,7 +993,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
987
993
  pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
988
994
 
989
995
  /* Otherwise, just call #exec_params instead for backward-compatibility */
990
- return pgconn_exec_params( argc, argv, self );
996
+ return pgconn_sync_exec_params( argc, argv, self );
991
997
 
992
998
  }
993
999
 
@@ -1019,7 +1025,7 @@ struct query_params_data {
1019
1025
  * Filled by alloc_query_params()
1020
1026
  */
1021
1027
 
1022
- /* Wraps the pointer of allocated memory, if function parameters dont't
1028
+ /* Wraps the pointer of allocated memory, if function parameters don't
1023
1029
  * fit in the memory_pool below.
1024
1030
  */
1025
1031
  VALUE heap_pool;
@@ -1037,7 +1043,7 @@ struct query_params_data {
1037
1043
  Oid *types;
1038
1044
 
1039
1045
  /* This array takes the string values for the timeframe of the query,
1040
- * if param value convertion is required
1046
+ * if param value conversion is required
1041
1047
  */
1042
1048
  VALUE gc_array;
1043
1049
 
@@ -1051,8 +1057,9 @@ struct query_params_data {
1051
1057
  };
1052
1058
 
1053
1059
  static void
1054
- free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1060
+ free_typecast_heap_chain(void *_chain_entry)
1055
1061
  {
1062
+ struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
1056
1063
  while(chain_entry){
1057
1064
  struct linked_typecast_data *next = chain_entry->next;
1058
1065
  xfree(chain_entry);
@@ -1060,6 +1067,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1060
1067
  }
1061
1068
  }
1062
1069
 
1070
+ static const rb_data_type_t pg_typecast_buffer_type = {
1071
+ "PG::Connection typecast buffer chain",
1072
+ {
1073
+ (RUBY_DATA_FUNC) NULL,
1074
+ free_typecast_heap_chain,
1075
+ (size_t (*)(const void *))NULL,
1076
+ },
1077
+ 0,
1078
+ 0,
1079
+ RUBY_TYPED_FREE_IMMEDIATELY,
1080
+ };
1081
+
1063
1082
  static char *
1064
1083
  alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1065
1084
  {
@@ -1070,17 +1089,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1070
1089
  /* Did we already wrap a memory chain per T_DATA object? */
1071
1090
  if( NIL_P( *typecast_heap_chain ) ){
1072
1091
  /* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
1073
- *typecast_heap_chain = Data_Wrap_Struct( rb_cObject, NULL, free_typecast_heap_chain, allocated );
1092
+ *typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
1074
1093
  allocated->next = NULL;
1075
1094
  } else {
1076
1095
  /* Append to the chain */
1077
- allocated->next = DATA_PTR( *typecast_heap_chain );
1078
- DATA_PTR( *typecast_heap_chain ) = allocated;
1096
+ allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
1097
+ RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
1079
1098
  }
1080
1099
 
1081
1100
  return &allocated->data[0];
1082
1101
  }
1083
1102
 
1103
+ static const rb_data_type_t pg_query_heap_pool_type = {
1104
+ "PG::Connection query heap pool",
1105
+ {
1106
+ (RUBY_DATA_FUNC) NULL,
1107
+ RUBY_TYPED_DEFAULT_FREE,
1108
+ (size_t (*)(const void *))NULL,
1109
+ },
1110
+ 0,
1111
+ 0,
1112
+ RUBY_TYPED_FREE_IMMEDIATELY,
1113
+ };
1084
1114
 
1085
1115
  static int
1086
1116
  alloc_query_params(struct query_params_data *paramsData)
@@ -1095,7 +1125,7 @@ alloc_query_params(struct query_params_data *paramsData)
1095
1125
 
1096
1126
  Check_Type(paramsData->params, T_ARRAY);
1097
1127
 
1098
- p_typemap = DATA_PTR( paramsData->typemap );
1128
+ p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
1099
1129
  p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
1100
1130
 
1101
1131
  paramsData->heap_pool = Qnil;
@@ -1114,7 +1144,7 @@ alloc_query_params(struct query_params_data *paramsData)
1114
1144
  /* Allocate one combined memory pool for all possible function parameters */
1115
1145
  memory_pool = (char*)xmalloc( required_pool_size );
1116
1146
  /* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
1117
- paramsData->heap_pool = Data_Wrap_Struct( rb_cObject, NULL, -1, memory_pool );
1147
+ paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
1118
1148
  required_pool_size = 0;
1119
1149
  }else{
1120
1150
  /* Use stack memory for function parameters */
@@ -1227,12 +1257,11 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1227
1257
  /* Use default typemap for queries. It's type is checked when assigned. */
1228
1258
  paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
1229
1259
  }else{
1260
+ t_typemap *tm;
1261
+ UNUSED(tm);
1262
+
1230
1263
  /* Check type of method param */
1231
- if ( !rb_obj_is_kind_of(paramsData->typemap, rb_cTypeMap) ) {
1232
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1233
- rb_obj_classname( paramsData->typemap ) );
1234
- }
1235
- Check_Type( paramsData->typemap, T_DATA );
1264
+ TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
1236
1265
  }
1237
1266
  }
1238
1267
 
@@ -1246,7 +1275,7 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1246
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.
1247
1276
  */
1248
1277
  static VALUE
1249
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1278
+ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1250
1279
  {
1251
1280
  t_pg_connection *this = pg_get_connection_safe( self );
1252
1281
  PGresult *result = NULL;
@@ -1266,7 +1295,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1266
1295
  */
1267
1296
  if ( NIL_P(paramsData.params) ) {
1268
1297
  pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1269
- return pgconn_exec( 1, argv, self );
1298
+ return pgconn_sync_exec( 1, argv, self );
1270
1299
  }
1271
1300
  pgconn_query_assign_typemap( self, &paramsData );
1272
1301
 
@@ -1297,7 +1326,7 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1297
1326
  * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1298
1327
  */
1299
1328
  static VALUE
1300
- pgconn_prepare(int argc, VALUE *argv, VALUE self)
1329
+ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1301
1330
  {
1302
1331
  t_pg_connection *this = pg_get_connection_safe( self );
1303
1332
  PGresult *result = NULL;
@@ -1346,7 +1375,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1346
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.
1347
1376
  */
1348
1377
  static VALUE
1349
- pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1378
+ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1350
1379
  {
1351
1380
  t_pg_connection *this = pg_get_connection_safe( self );
1352
1381
  PGresult *result = NULL;
@@ -1391,7 +1420,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1391
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.
1392
1421
  */
1393
1422
  static VALUE
1394
- pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1423
+ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1395
1424
  {
1396
1425
  PGresult *result;
1397
1426
  VALUE rb_pgresult;
@@ -1419,7 +1448,7 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1419
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.
1420
1449
  */
1421
1450
  static VALUE
1422
- pgconn_describe_portal(self, stmt_name)
1451
+ pgconn_sync_describe_portal(self, stmt_name)
1423
1452
  VALUE self, stmt_name;
1424
1453
  {
1425
1454
  PGresult *result;
@@ -1454,6 +1483,9 @@ pgconn_describe_portal(self, stmt_name)
1454
1483
  * * +PGRES_NONFATAL_ERROR+
1455
1484
  * * +PGRES_FATAL_ERROR+
1456
1485
  * * +PGRES_COPY_BOTH+
1486
+ * * +PGRES_SINGLE_TUPLE+
1487
+ * * +PGRES_PIPELINE_SYNC+
1488
+ * * +PGRES_PIPELINE_ABORTED+
1457
1489
  */
1458
1490
  static VALUE
1459
1491
  pgconn_make_empty_pgresult(VALUE self, VALUE status)
@@ -1750,6 +1782,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1750
1782
  rb_iv_set(error, "@connection", self);
1751
1783
  rb_exc_raise(error);
1752
1784
  }
1785
+ pgconn_wait_for_flush( self );
1753
1786
  return Qnil;
1754
1787
  }
1755
1788
 
@@ -1779,7 +1812,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1779
1812
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1780
1813
  * { :value => <string value>, :type => 0, :format => 0 }
1781
1814
  *
1782
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1815
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1783
1816
  * inside the SQL query. The 0th element of the +params+ array is bound
1784
1817
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1785
1818
  *
@@ -1827,6 +1860,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1827
1860
  rb_iv_set(error, "@connection", self);
1828
1861
  rb_exc_raise(error);
1829
1862
  }
1863
+ pgconn_wait_for_flush( self );
1830
1864
  return Qnil;
1831
1865
  }
1832
1866
 
@@ -1847,7 +1881,7 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1847
1881
  *
1848
1882
  * For example: "SELECT $1::int"
1849
1883
  *
1850
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1884
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1851
1885
  * inside the SQL query.
1852
1886
  */
1853
1887
  static VALUE
@@ -1890,6 +1924,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1890
1924
  rb_iv_set(error, "@connection", self);
1891
1925
  rb_exc_raise(error);
1892
1926
  }
1927
+ pgconn_wait_for_flush( self );
1893
1928
  return Qnil;
1894
1929
  }
1895
1930
 
@@ -1911,7 +1946,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1911
1946
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1912
1947
  * { :value => <string value>, :format => 0 }
1913
1948
  *
1914
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1949
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1915
1950
  * inside the SQL query. The 0th element of the +params+ array is bound
1916
1951
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1917
1952
  *
@@ -1941,7 +1976,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1941
1976
 
1942
1977
  if(NIL_P(paramsData.params)) {
1943
1978
  paramsData.params = rb_ary_new2(0);
1944
- resultFormat = 0;
1945
1979
  }
1946
1980
  pgconn_query_assign_typemap( self, &paramsData );
1947
1981
 
@@ -1959,6 +1993,7 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1959
1993
  rb_iv_set(error, "@connection", self);
1960
1994
  rb_exc_raise(error);
1961
1995
  }
1996
+ pgconn_wait_for_flush( self );
1962
1997
  return Qnil;
1963
1998
  }
1964
1999
 
@@ -1980,6 +2015,7 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
1980
2015
  rb_iv_set(error, "@connection", self);
1981
2016
  rb_exc_raise(error);
1982
2017
  }
2018
+ pgconn_wait_for_flush( self );
1983
2019
  return Qnil;
1984
2020
  }
1985
2021
 
@@ -2002,28 +2038,13 @@ pgconn_send_describe_portal(VALUE self, VALUE portal)
2002
2038
  rb_iv_set(error, "@connection", self);
2003
2039
  rb_exc_raise(error);
2004
2040
  }
2041
+ pgconn_wait_for_flush( self );
2005
2042
  return Qnil;
2006
2043
  }
2007
2044
 
2008
2045
 
2009
- /*
2010
- * call-seq:
2011
- * conn.get_result() -> PG::Result
2012
- * conn.get_result() {|pg_result| block }
2013
- *
2014
- * Blocks waiting for the next result from a call to
2015
- * #send_query (or another asynchronous command), and returns
2016
- * it. Returns +nil+ if no more results are available.
2017
- *
2018
- * Note: call this function repeatedly until it returns +nil+, or else
2019
- * you will not be able to issue further commands.
2020
- *
2021
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
2022
- * and the PG::Result object will automatically be cleared when the block terminates.
2023
- * In this instance, <code>conn.exec</code> returns the value of the block.
2024
- */
2025
2046
  static VALUE
2026
- pgconn_get_result(VALUE self)
2047
+ pgconn_sync_get_result(VALUE self)
2027
2048
  {
2028
2049
  PGconn *conn = pg_get_pgconn(self);
2029
2050
  PGresult *result;
@@ -2056,6 +2077,7 @@ pgconn_consume_input(self)
2056
2077
  PGconn *conn = pg_get_pgconn(self);
2057
2078
  /* returns 0 on error */
2058
2079
  if(PQconsumeInput(conn) == 0) {
2080
+ pgconn_close_socket_io(self);
2059
2081
  error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2060
2082
  rb_iv_set(error, "@connection", self);
2061
2083
  rb_exc_raise(error);
@@ -2068,7 +2090,7 @@ pgconn_consume_input(self)
2068
2090
  * conn.is_busy() -> Boolean
2069
2091
  *
2070
2092
  * Returns +true+ if a command is busy, that is, if
2071
- * PQgetResult would block. Otherwise returns +false+.
2093
+ * #get_result would block. Otherwise returns +false+.
2072
2094
  */
2073
2095
  static VALUE
2074
2096
  pgconn_is_busy(self)
@@ -2077,24 +2099,8 @@ pgconn_is_busy(self)
2077
2099
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2078
2100
  }
2079
2101
 
2080
- /*
2081
- * call-seq:
2082
- * conn.setnonblocking(Boolean) -> nil
2083
- *
2084
- * Sets the nonblocking status of the connection.
2085
- * In the blocking state, calls to #send_query
2086
- * will block until the message is sent to the server,
2087
- * but will not wait for the query results.
2088
- * In the nonblocking state, calls to #send_query
2089
- * will return an error if the socket is not ready for
2090
- * writing.
2091
- * Note: This function does not affect #exec, because
2092
- * that function doesn't return until the server has
2093
- * processed the query and returned the results.
2094
- * Returns +nil+.
2095
- */
2096
2102
  static VALUE
2097
- pgconn_setnonblocking(self, state)
2103
+ pgconn_sync_setnonblocking(self, state)
2098
2104
  VALUE self, state;
2099
2105
  {
2100
2106
  int arg;
@@ -2116,33 +2122,15 @@ pgconn_setnonblocking(self, state)
2116
2122
  }
2117
2123
 
2118
2124
 
2119
- /*
2120
- * call-seq:
2121
- * conn.isnonblocking() -> Boolean
2122
- *
2123
- * Returns +true+ if a command is busy, that is, if
2124
- * PQgetResult would block. Otherwise returns +false+.
2125
- */
2126
2125
  static VALUE
2127
- pgconn_isnonblocking(self)
2126
+ pgconn_sync_isnonblocking(self)
2128
2127
  VALUE self;
2129
2128
  {
2130
2129
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2131
2130
  }
2132
2131
 
2133
- /*
2134
- * call-seq:
2135
- * conn.flush() -> Boolean
2136
- *
2137
- * Attempts to flush any queued output data to the server.
2138
- * Returns +true+ if data is successfully flushed, +false+
2139
- * if not (can only return +false+ if connection is
2140
- * nonblocking.
2141
- * Raises PG::Error if some other failure occurred.
2142
- */
2143
2132
  static VALUE
2144
- pgconn_flush(self)
2145
- VALUE self;
2133
+ pgconn_sync_flush(VALUE self)
2146
2134
  {
2147
2135
  PGconn *conn = pg_get_pgconn(self);
2148
2136
  int ret;
@@ -2156,18 +2144,8 @@ pgconn_flush(self)
2156
2144
  return (ret) ? Qfalse : Qtrue;
2157
2145
  }
2158
2146
 
2159
- /*
2160
- * call-seq:
2161
- * conn.cancel() -> String
2162
- *
2163
- * Requests cancellation of the command currently being
2164
- * processed. (Only implemented in PostgreSQL >= 8.0)
2165
- *
2166
- * Returns +nil+ on success, or a string containing the
2167
- * error message if a failure occurs.
2168
- */
2169
2147
  static VALUE
2170
- pgconn_cancel(VALUE self)
2148
+ pgconn_sync_cancel(VALUE self)
2171
2149
  {
2172
2150
  char errbuf[256];
2173
2151
  PGcancel *cancel;
@@ -2178,7 +2156,7 @@ pgconn_cancel(VALUE self)
2178
2156
  if(cancel == NULL)
2179
2157
  rb_raise(rb_ePGerror,"Invalid connection!");
2180
2158
 
2181
- ret = gvl_PQcancel(cancel, errbuf, 256);
2159
+ ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2182
2160
  if(ret == 1)
2183
2161
  retval = Qnil;
2184
2162
  else
@@ -2229,107 +2207,50 @@ pgconn_notifies(VALUE self)
2229
2207
  return hash;
2230
2208
  }
2231
2209
 
2232
- /* Win32 + Ruby 1.9+ */
2233
- #if defined( _WIN32 )
2234
- /*
2235
- * On Windows, use platform-specific strategies to wait for the socket
2236
- * instead of rb_wait_for_single_fd().
2237
- */
2238
2210
 
2239
- int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2211
+ #if !defined(HAVE_RB_IO_WAIT)
2212
+ /* For compat with ruby < 3.0 */
2240
2213
 
2241
- static void *
2242
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2243
- {
2244
- int sd = PQsocket( conn );
2245
- void *retval;
2246
- struct timeval aborttime={0,0}, currtime, waittime;
2247
- DWORD timeout_milisec = INFINITE;
2248
- DWORD wait_ret;
2249
- WSAEVENT hEvent;
2250
-
2251
- if ( sd < 0 )
2252
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2253
-
2254
- hEvent = WSACreateEvent();
2255
-
2256
- /* Check for connection errors (PQisBusy is true on connection errors) */
2257
- if( PQconsumeInput(conn) == 0 ) {
2258
- WSACloseEvent( hEvent );
2259
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2260
- }
2261
-
2262
- if ( ptimeout ) {
2263
- gettimeofday(&currtime, NULL);
2264
- timeradd(&currtime, ptimeout, &aborttime);
2265
- }
2214
+ typedef enum {
2215
+ RUBY_IO_READABLE = RB_WAITFD_IN,
2216
+ RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2217
+ RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2218
+ } rb_io_event_t;
2266
2219
 
2267
- while ( !(retval=is_readable(conn)) ) {
2268
- if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2269
- WSACloseEvent( hEvent );
2270
- rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2271
- }
2272
-
2273
- if ( ptimeout ) {
2274
- gettimeofday(&currtime, NULL);
2275
- timersub(&aborttime, &currtime, &waittime);
2276
- timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
2277
- }
2278
-
2279
- /* Is the given timeout valid? */
2280
- if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2281
- /* Wait for the socket to become readable before checking again */
2282
- wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2283
- } else {
2284
- wait_ret = WAIT_TIMEOUT;
2285
- }
2286
-
2287
- if ( wait_ret == WAIT_TIMEOUT ) {
2288
- WSACloseEvent( hEvent );
2289
- return NULL;
2290
- } else if ( wait_ret == WAIT_OBJECT_0 ) {
2291
- /* The event we were waiting for. */
2292
- } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2293
- /* This indicates interruption from timer thread, GC, exception
2294
- * from other threads etc... */
2295
- rb_thread_check_ints();
2296
- } else if ( wait_ret == WAIT_FAILED ) {
2297
- WSACloseEvent( hEvent );
2298
- rb_raise( rb_eConnectionBad, "Wait on socket error (WaitForMultipleObjects): %lu", GetLastError() );
2299
- } else {
2300
- WSACloseEvent( hEvent );
2301
- rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
2302
- }
2303
-
2304
- /* Check for connection errors (PQisBusy is true on connection errors) */
2305
- if ( PQconsumeInput(conn) == 0 ) {
2306
- WSACloseEvent( hEvent );
2307
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2308
- }
2220
+ static VALUE
2221
+ rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2222
+ rb_io_t *fptr;
2223
+ struct timeval waittime;
2224
+ int res;
2225
+
2226
+ GetOpenFile((io), fptr);
2227
+ if( !NIL_P(timeout) ){
2228
+ waittime.tv_sec = (time_t)(NUM2DBL(timeout));
2229
+ waittime.tv_usec = (time_t)(NUM2DBL(timeout) - (double)waittime.tv_sec);
2309
2230
  }
2231
+ res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
2310
2232
 
2311
- WSACloseEvent( hEvent );
2312
- return retval;
2233
+ return UINT2NUM(res);
2313
2234
  }
2314
-
2315
- #else
2316
-
2317
- /* non Win32 */
2235
+ #endif
2318
2236
 
2319
2237
  static void *
2320
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2238
+ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2321
2239
  {
2322
- int sd = PQsocket( conn );
2323
- int ret;
2240
+ VALUE socket_io;
2241
+ VALUE ret;
2324
2242
  void *retval;
2325
2243
  struct timeval aborttime={0,0}, currtime, waittime;
2244
+ VALUE wait_timeout = Qnil;
2245
+ PGconn *conn = pg_get_pgconn(self);
2326
2246
 
2327
- if ( sd < 0 )
2328
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2247
+ socket_io = pgconn_socket_io(self);
2329
2248
 
2330
2249
  /* Check for connection errors (PQisBusy is true on connection errors) */
2331
- if ( PQconsumeInput(conn) == 0 )
2250
+ if ( PQconsumeInput(conn) == 0 ) {
2251
+ pgconn_close_socket_io(self);
2332
2252
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2253
+ }
2333
2254
 
2334
2255
  if ( ptimeout ) {
2335
2256
  gettimeofday(&currtime, NULL);
@@ -2340,27 +2261,25 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2340
2261
  if ( ptimeout ) {
2341
2262
  gettimeofday(&currtime, NULL);
2342
2263
  timersub(&aborttime, &currtime, &waittime);
2264
+ wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
2343
2265
  }
2344
2266
 
2345
2267
  /* Is the given timeout valid? */
2346
2268
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2347
2269
  /* Wait for the socket to become readable before checking again */
2348
- ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
2270
+ ret = rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), wait_timeout);
2349
2271
  } else {
2350
- ret = 0;
2351
- }
2352
-
2353
- if ( ret < 0 ){
2354
- rb_sys_fail( "rb_wait_for_single_fd()" );
2272
+ ret = Qfalse;
2355
2273
  }
2356
2274
 
2357
2275
  /* Return false if the select() timed out */
2358
- if ( ret == 0 ){
2276
+ if ( ret == Qfalse ){
2359
2277
  return NULL;
2360
2278
  }
2361
2279
 
2362
2280
  /* Check for connection errors (PQisBusy is true on connection errors) */
2363
2281
  if ( PQconsumeInput(conn) == 0 ){
2282
+ pgconn_close_socket_io(self);
2364
2283
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2365
2284
  }
2366
2285
  }
@@ -2368,8 +2287,45 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2368
2287
  return retval;
2369
2288
  }
2370
2289
 
2290
+ /*
2291
+ * call-seq:
2292
+ * conn.flush() -> Boolean
2293
+ *
2294
+ * Attempts to flush any queued output data to the server.
2295
+ * Returns +true+ if data is successfully flushed, +false+
2296
+ * if not (can only return +false+ if connection is
2297
+ * nonblocking.
2298
+ * Raises PG::Error if some other failure occurred.
2299
+ */
2300
+ static VALUE
2301
+ pgconn_async_flush(VALUE self)
2302
+ {
2303
+ while( pgconn_sync_flush(self) == Qfalse ){
2304
+ /* wait for the socket to become read- or write-ready */
2305
+ int events;
2306
+ VALUE socket_io = pgconn_socket_io(self);
2307
+ events = RB_NUM2INT(rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE | RUBY_IO_WRITABLE), Qnil));
2308
+
2309
+ if (events & RUBY_IO_READABLE)
2310
+ pgconn_consume_input(self);
2311
+ }
2312
+ return Qtrue;
2313
+ }
2314
+
2315
+ static VALUE
2316
+ pgconn_wait_for_flush( VALUE self ){
2317
+ if( !pg_get_connection_safe(self)->flush_data )
2318
+ return Qnil;
2371
2319
 
2372
- #endif
2320
+ return pgconn_async_flush(self);
2321
+ }
2322
+
2323
+ static VALUE
2324
+ pgconn_flush_data_set( VALUE self, VALUE enabled ){
2325
+ t_pg_connection *conn = pg_get_connection(self);
2326
+ conn->flush_data = RTEST(enabled);
2327
+ return enabled;
2328
+ }
2373
2329
 
2374
2330
  static void *
2375
2331
  notify_readable(PGconn *conn)
@@ -2408,7 +2364,7 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2408
2364
  ptimeout = &timeout;
2409
2365
  }
2410
2366
 
2411
- pnotification = (PGnotify*) wait_socket_readable( this->pgconn, ptimeout, notify_readable);
2367
+ pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
2412
2368
 
2413
2369
  /* Return nil if the select timed out */
2414
2370
  if ( !pnotification ) return Qnil;
@@ -2429,28 +2385,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2429
2385
  }
2430
2386
 
2431
2387
 
2432
- /*
2433
- * call-seq:
2434
- * conn.put_copy_data( buffer [, encoder] ) -> Boolean
2435
- *
2436
- * Transmits _buffer_ as copy data to the server.
2437
- * Returns true if the data was sent, false if it was
2438
- * not sent (false is only possible if the connection
2439
- * is in nonblocking mode, and this command would block).
2440
- *
2441
- * _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
2442
- * This encodes the data fields given as _buffer_ from an Array of Strings to
2443
- * PostgreSQL's COPY text format inclusive proper escaping. Optionally
2444
- * the encoder can type cast the fields from various Ruby types in one step,
2445
- * if PG::TextEncoder::CopyRow#type_map is set accordingly.
2446
- *
2447
- * Raises an exception if an error occurs.
2448
- *
2449
- * See also #copy_data.
2450
- *
2451
- */
2452
2388
  static VALUE
2453
- pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2389
+ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2454
2390
  {
2455
2391
  int ret;
2456
2392
  int len;
@@ -2467,13 +2403,11 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2467
2403
  if( NIL_P(this->encoder_for_put_copy_data) ){
2468
2404
  buffer = value;
2469
2405
  } else {
2470
- p_coder = DATA_PTR( this->encoder_for_put_copy_data );
2406
+ p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
2471
2407
  }
2472
- } else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
2473
- Data_Get_Struct( encoder, t_pg_coder, p_coder );
2474
2408
  } else {
2475
- rb_raise( rb_eTypeError, "wrong encoder type %s (expected some kind of PG::Coder)",
2476
- rb_obj_classname( encoder ) );
2409
+ /* Check argument type and use argument encoder */
2410
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
2477
2411
  }
2478
2412
 
2479
2413
  if( p_coder ){
@@ -2507,22 +2441,8 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2507
2441
  return (ret) ? Qtrue : Qfalse;
2508
2442
  }
2509
2443
 
2510
- /*
2511
- * call-seq:
2512
- * conn.put_copy_end( [ error_message ] ) -> Boolean
2513
- *
2514
- * Sends end-of-data indication to the server.
2515
- *
2516
- * _error_message_ is an optional parameter, and if set,
2517
- * forces the COPY command to fail with the string
2518
- * _error_message_.
2519
- *
2520
- * Returns true if the end-of-data was sent, false if it was
2521
- * not sent (false is only possible if the connection
2522
- * is in nonblocking mode, and this command would block).
2523
- */
2524
2444
  static VALUE
2525
- pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2445
+ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2526
2446
  {
2527
2447
  VALUE str;
2528
2448
  VALUE error;
@@ -2544,27 +2464,8 @@ pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2544
2464
  return (ret) ? Qtrue : Qfalse;
2545
2465
  }
2546
2466
 
2547
- /*
2548
- * call-seq:
2549
- * conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
2550
- *
2551
- * Return one row of data, +nil+
2552
- * if the copy is done, or +false+ if the call would
2553
- * block (only possible if _async_ is true).
2554
- *
2555
- * If _decoder_ is not set or +nil+, data is returned as binary string.
2556
- *
2557
- * If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
2558
- * PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
2559
- * COPY text format to an Array of Strings.
2560
- * Optionally the decoder can type cast the single fields to various Ruby types in one step,
2561
- * if PG::TextDecoder::CopyRow#type_map is set accordingly.
2562
- *
2563
- * See also #copy_data.
2564
- *
2565
- */
2566
2467
  static VALUE
2567
- pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2468
+ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2568
2469
  {
2569
2470
  VALUE async_in;
2570
2471
  VALUE error;
@@ -2579,13 +2480,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2579
2480
 
2580
2481
  if( NIL_P(decoder) ){
2581
2482
  if( !NIL_P(this->decoder_for_get_copy_data) ){
2582
- p_coder = DATA_PTR( this->decoder_for_get_copy_data );
2483
+ p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
2583
2484
  }
2584
- } else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
2585
- Data_Get_Struct( decoder, t_pg_coder, p_coder );
2586
2485
  } else {
2587
- rb_raise( rb_eTypeError, "wrong decoder type %s (expected some kind of PG::Coder)",
2588
- rb_obj_classname( decoder ) );
2486
+ /* Check argument type and use argument decoder */
2487
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
2589
2488
  }
2590
2489
 
2591
2490
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
@@ -2830,7 +2729,7 @@ notice_processor_proxy(void *arg, const char *message)
2830
2729
  * call-seq:
2831
2730
  * conn.set_notice_processor {|message| ... } -> Proc
2832
2731
  *
2833
- * See #set_notice_receiver for the desription of what this and the
2732
+ * See #set_notice_receiver for the description of what this and the
2834
2733
  * notice_processor methods do.
2835
2734
  *
2836
2735
  * This function takes a new block to act as the notice processor and returns
@@ -2884,12 +2783,14 @@ pgconn_get_client_encoding(VALUE self)
2884
2783
 
2885
2784
  /*
2886
2785
  * call-seq:
2887
- * conn.set_client_encoding( encoding )
2786
+ * conn.sync_set_client_encoding( encoding )
2888
2787
  *
2889
- * Sets the client encoding to the _encoding_ String.
2788
+ * This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
2789
+ * See #async_exec for the differences between the two API variants.
2790
+ * 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.
2890
2791
  */
2891
2792
  static VALUE
2892
- pgconn_set_client_encoding(VALUE self, VALUE str)
2793
+ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2893
2794
  {
2894
2795
  PGconn *conn = pg_get_pgconn( self );
2895
2796
 
@@ -2903,49 +2804,6 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
2903
2804
  return Qnil;
2904
2805
  }
2905
2806
 
2906
- /*
2907
- * call-seq:
2908
- * conn.transaction { |conn| ... } -> result of the block
2909
- *
2910
- * Executes a +BEGIN+ at the start of the block,
2911
- * and a +COMMIT+ at the end of the block, or
2912
- * +ROLLBACK+ if any exception occurs.
2913
- */
2914
- static VALUE
2915
- pgconn_transaction(VALUE self)
2916
- {
2917
- PGconn *conn = pg_get_pgconn(self);
2918
- PGresult *result;
2919
- VALUE rb_pgresult;
2920
- VALUE block_result = Qnil;
2921
- int status;
2922
-
2923
- if (rb_block_given_p()) {
2924
- result = gvl_PQexec(conn, "BEGIN");
2925
- rb_pgresult = pg_new_result(result, self);
2926
- pg_result_check(rb_pgresult);
2927
- block_result = rb_protect(rb_yield, self, &status);
2928
- if(status == 0) {
2929
- result = gvl_PQexec(conn, "COMMIT");
2930
- rb_pgresult = pg_new_result(result, self);
2931
- pg_result_check(rb_pgresult);
2932
- }
2933
- else {
2934
- /* exception occurred, ROLLBACK and re-raise */
2935
- result = gvl_PQexec(conn, "ROLLBACK");
2936
- rb_pgresult = pg_new_result(result, self);
2937
- pg_result_check(rb_pgresult);
2938
- rb_jump_tag(status);
2939
- }
2940
-
2941
- }
2942
- else {
2943
- /* no block supplied? */
2944
- rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
2945
- }
2946
- return block_result;
2947
- }
2948
-
2949
2807
 
2950
2808
  /*
2951
2809
  * call-seq:
@@ -3022,8 +2880,6 @@ get_result_readable(PGconn *conn)
3022
2880
  */
3023
2881
  static VALUE
3024
2882
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
3025
- PGconn *conn = pg_get_pgconn( self );
3026
-
3027
2883
  struct timeval timeout;
3028
2884
  struct timeval *ptimeout = NULL;
3029
2885
  VALUE timeout_in;
@@ -3037,7 +2893,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3037
2893
  ptimeout = &timeout;
3038
2894
  }
3039
2895
 
3040
- ret = wait_socket_readable( conn, ptimeout, get_result_readable);
2896
+ ret = wait_socket_readable( self, ptimeout, get_result_readable);
3041
2897
 
3042
2898
  if( !ret )
3043
2899
  return Qfalse;
@@ -3046,6 +2902,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3046
2902
  }
3047
2903
 
3048
2904
 
2905
+ /*
2906
+ * call-seq:
2907
+ * conn.sync_get_last_result( ) -> PG::Result
2908
+ *
2909
+ * This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
2910
+ * See #async_exec for the differences between the two API variants.
2911
+ * 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.
2912
+ */
2913
+ static VALUE
2914
+ pgconn_sync_get_last_result(VALUE self)
2915
+ {
2916
+ PGconn *conn = pg_get_pgconn(self);
2917
+ VALUE rb_pgresult = Qnil;
2918
+ PGresult *cur, *prev;
2919
+
2920
+
2921
+ cur = prev = NULL;
2922
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
2923
+ int status;
2924
+
2925
+ if (prev) PQclear(prev);
2926
+ prev = cur;
2927
+
2928
+ status = PQresultStatus(cur);
2929
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
2930
+ break;
2931
+ }
2932
+
2933
+ if (prev) {
2934
+ rb_pgresult = pg_new_result( prev, self );
2935
+ pg_result_check(rb_pgresult);
2936
+ }
2937
+
2938
+ return rb_pgresult;
2939
+ }
2940
+
3049
2941
  /*
3050
2942
  * call-seq:
3051
2943
  * conn.get_last_result( ) -> PG::Result
@@ -3056,27 +2948,35 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3056
2948
  * returns the last non-NULL result, or +nil+ if no
3057
2949
  * results are available.
3058
2950
  *
2951
+ * If the last result contains a bad result_status, an
2952
+ * appropriate exception is raised.
2953
+ *
3059
2954
  * This function is similar to #get_result
3060
2955
  * except that it is designed to get one and only
3061
- * one result.
2956
+ * one result and that it checks the result state.
3062
2957
  */
3063
2958
  static VALUE
3064
- pgconn_get_last_result(VALUE self)
2959
+ pgconn_async_get_last_result(VALUE self)
3065
2960
  {
3066
2961
  PGconn *conn = pg_get_pgconn(self);
3067
2962
  VALUE rb_pgresult = Qnil;
3068
2963
  PGresult *cur, *prev;
3069
2964
 
3070
-
3071
- cur = prev = NULL;
3072
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
2965
+ cur = prev = NULL;
2966
+ for(;;) {
3073
2967
  int status;
3074
2968
 
2969
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
2970
+
2971
+ cur = gvl_PQgetResult(conn);
2972
+ if (cur == NULL)
2973
+ break;
2974
+
3075
2975
  if (prev) PQclear(prev);
3076
2976
  prev = cur;
3077
2977
 
3078
2978
  status = PQresultStatus(cur);
3079
- if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
2979
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3080
2980
  break;
3081
2981
  }
3082
2982
 
@@ -3100,22 +3000,60 @@ static VALUE
3100
3000
  pgconn_discard_results(VALUE self)
3101
3001
  {
3102
3002
  PGconn *conn = pg_get_pgconn(self);
3003
+ VALUE socket_io;
3103
3004
 
3104
- PGresult *cur;
3105
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3106
- int status = PQresultStatus(cur);
3005
+ if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3006
+ return Qnil;
3007
+ }
3008
+
3009
+ socket_io = pgconn_socket_io(self);
3010
+
3011
+ for(;;) {
3012
+ PGresult *cur;
3013
+ int status;
3014
+
3015
+ /* pgconn_block() raises an exception in case of errors.
3016
+ * To avoid this call rb_io_wait() and PQconsumeInput() without rb_raise().
3017
+ */
3018
+ while( gvl_PQisBusy(conn) ){
3019
+ rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
3020
+ if ( PQconsumeInput(conn) == 0 ) {
3021
+ pgconn_close_socket_io(self);
3022
+ return Qfalse;
3023
+ }
3024
+ }
3025
+
3026
+ cur = gvl_PQgetResult(conn);
3027
+ if( cur == NULL) break;
3028
+
3029
+ status = PQresultStatus(cur);
3107
3030
  PQclear(cur);
3108
3031
  if (status == PGRES_COPY_IN){
3109
3032
  gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
3110
3033
  }
3111
3034
  if (status == PGRES_COPY_OUT){
3112
- char *buffer = NULL;
3113
- while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
3114
- PQfreemem(buffer);
3035
+ for(;;) {
3036
+ char *buffer = NULL;
3037
+ int st = gvl_PQgetCopyData(conn, &buffer, 1);
3038
+ if( st == 0 ) {
3039
+ /* would block -> wait for readable data */
3040
+ rb_io_wait(socket_io, RB_INT2NUM(RUBY_IO_READABLE), Qnil);
3041
+ if ( PQconsumeInput(conn) == 0 ) {
3042
+ pgconn_close_socket_io(self);
3043
+ return Qfalse;
3044
+ }
3045
+ } else if( st > 0 ) {
3046
+ /* some data retrieved -> discard it */
3047
+ PQfreemem(buffer);
3048
+ } else {
3049
+ /* no more data */
3050
+ break;
3051
+ }
3052
+ }
3115
3053
  }
3116
3054
  }
3117
3055
 
3118
- return Qnil;
3056
+ return Qtrue;
3119
3057
  }
3120
3058
 
3121
3059
  /*
@@ -3152,8 +3090,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3152
3090
 
3153
3091
  pgconn_discard_results( self );
3154
3092
  pgconn_send_query( argc, argv, self );
3155
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3156
- rb_pgresult = pgconn_get_last_result( self );
3093
+ rb_pgresult = pgconn_async_get_last_result( self );
3157
3094
 
3158
3095
  if ( rb_block_given_p() ) {
3159
3096
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3182,7 +3119,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3182
3119
  * or, it may be a String. If it is a string, that is equivalent to the hash:
3183
3120
  * { :value => <string value>, :type => 0, :format => 0 }
3184
3121
  *
3185
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3122
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3186
3123
  * inside the SQL query. The 0th element of the +params+ array is bound
3187
3124
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3188
3125
  *
@@ -3225,8 +3162,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3225
3162
  } else {
3226
3163
  pgconn_send_query_params( argc, argv, self );
3227
3164
  }
3228
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3229
- rb_pgresult = pgconn_get_last_result( self );
3165
+ rb_pgresult = pgconn_async_get_last_result( self );
3230
3166
 
3231
3167
  if ( rb_block_given_p() ) {
3232
3168
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3252,7 +3188,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3252
3188
  *
3253
3189
  * For example: "SELECT $1::int"
3254
3190
  *
3255
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3191
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3256
3192
  * inside the SQL query.
3257
3193
  *
3258
3194
  * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
@@ -3264,8 +3200,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3264
3200
 
3265
3201
  pgconn_discard_results( self );
3266
3202
  pgconn_send_prepare( argc, argv, self );
3267
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3268
- rb_pgresult = pgconn_get_last_result( self );
3203
+ rb_pgresult = pgconn_async_get_last_result( self );
3269
3204
 
3270
3205
  if ( rb_block_given_p() ) {
3271
3206
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3292,7 +3227,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3292
3227
  * or, it may be a String. If it is a string, that is equivalent to the hash:
3293
3228
  * { :value => <string value>, :format => 0 }
3294
3229
  *
3295
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
3230
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3296
3231
  * inside the SQL query. The 0th element of the +params+ array is bound
3297
3232
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3298
3233
  *
@@ -3318,8 +3253,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3318
3253
 
3319
3254
  pgconn_discard_results( self );
3320
3255
  pgconn_send_query_prepared( argc, argv, self );
3321
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3322
- rb_pgresult = pgconn_get_last_result( self );
3256
+ rb_pgresult = pgconn_async_get_last_result( self );
3323
3257
 
3324
3258
  if ( rb_block_given_p() ) {
3325
3259
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3343,8 +3277,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3343
3277
 
3344
3278
  pgconn_discard_results( self );
3345
3279
  pgconn_send_describe_portal( self, portal );
3346
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3347
- rb_pgresult = pgconn_get_last_result( self );
3280
+ rb_pgresult = pgconn_async_get_last_result( self );
3348
3281
 
3349
3282
  if ( rb_block_given_p() ) {
3350
3283
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3368,8 +3301,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3368
3301
 
3369
3302
  pgconn_discard_results( self );
3370
3303
  pgconn_send_describe_prepared( self, stmt_name );
3371
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3372
- rb_pgresult = pgconn_get_last_result( self );
3304
+ rb_pgresult = pgconn_async_get_last_result( self );
3373
3305
 
3374
3306
  if ( rb_block_given_p() ) {
3375
3307
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3457,6 +3389,126 @@ pgconn_ssl_attribute_names(VALUE self)
3457
3389
  #endif
3458
3390
 
3459
3391
 
3392
+ #ifdef HAVE_PQENTERPIPELINEMODE
3393
+ /*
3394
+ * call-seq:
3395
+ * conn.pipeline_status -> Integer
3396
+ *
3397
+ * Returns the current pipeline mode status of the libpq connection.
3398
+ *
3399
+ * PQpipelineStatus can return one of the following values:
3400
+ *
3401
+ * * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
3402
+ * * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
3403
+ * * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
3404
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
3405
+ *
3406
+ * Available since PostgreSQL-14
3407
+ */
3408
+ static VALUE
3409
+ pgconn_pipeline_status(VALUE self)
3410
+ {
3411
+ int res = PQpipelineStatus(pg_get_pgconn(self));
3412
+ return INT2FIX(res);
3413
+ }
3414
+
3415
+
3416
+ /*
3417
+ * call-seq:
3418
+ * conn.enter_pipeline_mode -> nil
3419
+ *
3420
+ * Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
3421
+ *
3422
+ * Raises PG::Error and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc.
3423
+ * This function does not actually send anything to the server, it just changes the libpq connection state.
3424
+ *
3425
+ * Available since PostgreSQL-14
3426
+ */
3427
+ static VALUE
3428
+ pgconn_enter_pipeline_mode(VALUE self)
3429
+ {
3430
+ PGconn *conn = pg_get_pgconn(self);
3431
+ int res = PQenterPipelineMode(conn);
3432
+ if( res == 1 ) {
3433
+ return Qnil;
3434
+ } else {
3435
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3436
+ }
3437
+ }
3438
+
3439
+ /*
3440
+ * call-seq:
3441
+ * conn.exit_pipeline_mode -> nil
3442
+ *
3443
+ * Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
3444
+ *
3445
+ * Takes no action if not in pipeline mode.
3446
+ * Raises PG::Error if the current statement isn't finished processing, or PQgetResult has not been called to collect results from all previously sent query.
3447
+ *
3448
+ * Available since PostgreSQL-14
3449
+ */
3450
+ static VALUE
3451
+ pgconn_exit_pipeline_mode(VALUE self)
3452
+ {
3453
+ PGconn *conn = pg_get_pgconn(self);
3454
+ int res = PQexitPipelineMode(conn);
3455
+ if( res == 1 ) {
3456
+ return Qnil;
3457
+ } else {
3458
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3459
+ }
3460
+ }
3461
+
3462
+
3463
+ /*
3464
+ * call-seq:
3465
+ * conn.pipeline_sync -> nil
3466
+ *
3467
+ * Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
3468
+ * This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
3469
+ *
3470
+ * Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
3471
+ *
3472
+ * Available since PostgreSQL-14
3473
+ */
3474
+ static VALUE
3475
+ pgconn_pipeline_sync(VALUE self)
3476
+ {
3477
+ PGconn *conn = pg_get_pgconn(self);
3478
+ int res = PQpipelineSync(conn);
3479
+ if( res == 1 ) {
3480
+ return Qnil;
3481
+ } else {
3482
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3483
+ }
3484
+ }
3485
+
3486
+ /*
3487
+ * call-seq:
3488
+ * conn.pipeline_sync -> nil
3489
+ *
3490
+ * Sends a request for the server to flush its output buffer.
3491
+ *
3492
+ * The server flushes its output buffer automatically as a result of Connection#pipeline_sync being called, or on any request when not in pipeline mode.
3493
+ * This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
3494
+ * Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
3495
+ *
3496
+ * Available since PostgreSQL-14
3497
+ */
3498
+ static VALUE
3499
+ pgconn_send_flush_request(VALUE self)
3500
+ {
3501
+ PGconn *conn = pg_get_pgconn(self);
3502
+ int res = PQsendFlushRequest(conn);
3503
+ if( res == 1 ) {
3504
+ return Qnil;
3505
+ } else {
3506
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3507
+ }
3508
+ }
3509
+
3510
+ #endif
3511
+
3460
3512
  /**************************************************************************
3461
3513
  * LARGE OBJECT SUPPORT
3462
3514
  **************************************************************************/
@@ -3801,11 +3853,11 @@ static VALUE
3801
3853
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3802
3854
  {
3803
3855
  if (NIL_P(enc)) {
3804
- pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3856
+ pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3805
3857
  return enc;
3806
3858
  }
3807
3859
  else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
3808
- pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3860
+ pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3809
3861
  return enc;
3810
3862
  }
3811
3863
  else {
@@ -3843,16 +3895,33 @@ pgconn_external_encoding(VALUE self)
3843
3895
  return rb_enc_from_encoding( enc );
3844
3896
  }
3845
3897
 
3898
+ /*
3899
+ * call-seq:
3900
+ * conn.set_client_encoding( encoding )
3901
+ *
3902
+ * Sets the client encoding to the _encoding_ String.
3903
+ */
3904
+ static VALUE
3905
+ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
3906
+ {
3907
+ VALUE query_format, query;
3908
+
3909
+ Check_Type(encname, T_STRING);
3910
+ query_format = rb_str_new_cstr("set client_encoding to '%s'");
3911
+ query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3912
+
3913
+ pgconn_async_exec(1, &query, self);
3914
+ pgconn_set_internal_encoding_index( self );
3915
+
3916
+ return Qnil;
3917
+ }
3846
3918
 
3847
3919
  static VALUE
3848
3920
  pgconn_set_client_encoding_async1( VALUE args )
3849
3921
  {
3850
3922
  VALUE self = ((VALUE*)args)[0];
3851
3923
  VALUE encname = ((VALUE*)args)[1];
3852
- VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3853
- VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3854
-
3855
- pgconn_async_exec(1, &query, self);
3924
+ pgconn_async_set_client_encoding(self, encname);
3856
3925
  return 0;
3857
3926
  }
3858
3927
 
@@ -3867,9 +3936,9 @@ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3867
3936
 
3868
3937
 
3869
3938
  static VALUE
3870
- pgconn_set_client_encoding_async( VALUE self, const char *encname )
3939
+ pgconn_set_client_encoding_async( VALUE self, VALUE encname )
3871
3940
  {
3872
- VALUE args[] = { self, rb_str_new_cstr(encname) };
3941
+ VALUE args[] = { self, encname };
3873
3942
  return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3874
3943
  }
3875
3944
 
@@ -3891,10 +3960,9 @@ pgconn_set_default_encoding( VALUE self )
3891
3960
 
3892
3961
  if (( enc = rb_default_internal_encoding() )) {
3893
3962
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3894
- if ( pgconn_set_client_encoding_async(self, encname) != 0 )
3963
+ if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
3895
3964
  rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
3896
3965
  encname, PQerrorMessage(conn) );
3897
- pgconn_set_internal_encoding_index( self );
3898
3966
  return rb_enc_from_encoding( enc );
3899
3967
  } else {
3900
3968
  pgconn_set_internal_encoding_index( self );
@@ -3916,12 +3984,12 @@ static VALUE
3916
3984
  pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
3917
3985
  {
3918
3986
  t_pg_connection *this = pg_get_connection( self );
3987
+ t_typemap *tm;
3988
+ UNUSED(tm);
3989
+
3990
+ /* Check type of method param */
3991
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3919
3992
 
3920
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3921
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3922
- rb_obj_classname( typemap ) );
3923
- }
3924
- Check_Type(typemap, T_DATA);
3925
3993
  this->type_map_for_queries = typemap;
3926
3994
 
3927
3995
  return typemap;
@@ -3956,12 +4024,10 @@ static VALUE
3956
4024
  pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
3957
4025
  {
3958
4026
  t_pg_connection *this = pg_get_connection( self );
4027
+ t_typemap *tm;
4028
+ UNUSED(tm);
3959
4029
 
3960
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3961
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3962
- rb_obj_classname( typemap ) );
3963
- }
3964
- Check_Type(typemap, T_DATA);
4030
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3965
4031
  this->type_map_for_results = typemap;
3966
4032
 
3967
4033
  return typemap;
@@ -3996,20 +4062,19 @@ pgconn_type_map_for_results_get(VALUE self)
3996
4062
  *
3997
4063
  */
3998
4064
  static VALUE
3999
- pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
4065
+ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
4000
4066
  {
4001
4067
  t_pg_connection *this = pg_get_connection( self );
4002
4068
 
4003
- if( typemap != Qnil ){
4004
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
4005
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
4006
- rb_obj_classname( typemap ) );
4007
- }
4008
- Check_Type(typemap, T_DATA);
4069
+ if( encoder != Qnil ){
4070
+ t_pg_coder *co;
4071
+ UNUSED(co);
4072
+ /* Check argument type */
4073
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
4009
4074
  }
4010
- this->encoder_for_put_copy_data = typemap;
4075
+ this->encoder_for_put_copy_data = encoder;
4011
4076
 
4012
- return typemap;
4077
+ return encoder;
4013
4078
  }
4014
4079
 
4015
4080
  /*
@@ -4045,20 +4110,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
4045
4110
  *
4046
4111
  */
4047
4112
  static VALUE
4048
- pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE typemap)
4113
+ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4049
4114
  {
4050
4115
  t_pg_connection *this = pg_get_connection( self );
4051
4116
 
4052
- if( typemap != Qnil ){
4053
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
4054
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
4055
- rb_obj_classname( typemap ) );
4056
- }
4057
- Check_Type(typemap, T_DATA);
4117
+ if( decoder != Qnil ){
4118
+ t_pg_coder *co;
4119
+ UNUSED(co);
4120
+ /* Check argument type */
4121
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
4058
4122
  }
4059
- this->decoder_for_get_copy_data = typemap;
4123
+ this->decoder_for_get_copy_data = decoder;
4060
4124
 
4061
- return typemap;
4125
+ return decoder;
4062
4126
  }
4063
4127
 
4064
4128
  /*
@@ -4141,6 +4205,7 @@ void
4141
4205
  init_pg_connection()
4142
4206
  {
4143
4207
  s_id_encode = rb_intern("encode");
4208
+ s_id_autoclose_set = rb_intern("autoclose=");
4144
4209
  sym_type = ID2SYM(rb_intern("type"));
4145
4210
  sym_format = ID2SYM(rb_intern("format"));
4146
4211
  sym_value = ID2SYM(rb_intern("value"));
@@ -4156,10 +4221,6 @@ init_pg_connection()
4156
4221
  /****** PG::Connection CLASS METHODS ******/
4157
4222
  rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
4158
4223
 
4159
- SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
4160
- SINGLETON_ALIAS(rb_cPGconn, "open", "new");
4161
- SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
4162
- SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
4163
4224
  rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4164
4225
  SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
4165
4226
  rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
@@ -4168,14 +4229,14 @@ init_pg_connection()
4168
4229
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4169
4230
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4170
4231
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4171
- rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
4232
+ rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4233
+ rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4172
4234
 
4173
4235
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
4174
- rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
4175
4236
  rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
4176
4237
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
4177
4238
  rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
4178
- rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
4239
+ rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
4179
4240
  rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
4180
4241
  rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
4181
4242
  rb_define_alias(rb_cPGconn, "close", "finish");
@@ -4187,9 +4248,7 @@ init_pg_connection()
4187
4248
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4188
4249
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4189
4250
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4190
- #ifdef HAVE_PQCONNINFO
4191
4251
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
4192
- #endif
4193
4252
  rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
4194
4253
  rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
4195
4254
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
@@ -4200,17 +4259,18 @@ init_pg_connection()
4200
4259
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
4201
4260
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
4202
4261
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4262
+ rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
4203
4263
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
4204
4264
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
4205
4265
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
4206
4266
 
4207
4267
  /****** PG::Connection INSTANCE METHODS: Command Execution ******/
4208
- rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
4209
- rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
4210
- rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
4211
- rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
4212
- rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
4213
- rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
4268
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
4269
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
4270
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
4271
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4272
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4273
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4214
4274
 
4215
4275
  rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4216
4276
  rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
@@ -4243,25 +4303,26 @@ init_pg_connection()
4243
4303
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
4244
4304
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
4245
4305
  rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
4246
- rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
4306
+ rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
4247
4307
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4248
4308
  rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
4249
- rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
4250
- rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
4251
- rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
4252
- rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
4309
+ rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
4310
+ rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
4311
+ rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
4312
+ rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
4313
+ rb_define_alias(rb_cPGconn, "async_flush", "flush");
4253
4314
  rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4254
4315
 
4255
4316
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4256
- rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
4317
+ rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4257
4318
 
4258
4319
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4259
4320
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
4260
4321
 
4261
4322
  /****** PG::Connection INSTANCE METHODS: COPY ******/
4262
- rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, -1);
4263
- rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
4264
- rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
4323
+ rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
4324
+ rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
4325
+ rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
4265
4326
 
4266
4327
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4267
4328
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
@@ -4277,16 +4338,20 @@ init_pg_connection()
4277
4338
 
4278
4339
  /****** PG::Connection INSTANCE METHODS: Other ******/
4279
4340
  rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
4280
- rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
4341
+ rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
4342
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
4343
+ rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
4281
4344
  rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
4282
- rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
4283
4345
  rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
4346
+ rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
4284
4347
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
4285
4348
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
4286
4349
  rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4287
- rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
4350
+ rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4351
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4352
+ rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4288
4353
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
4289
- rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
4354
+ rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4290
4355
  #endif
4291
4356
 
4292
4357
  #ifdef HAVE_PQSSLATTRIBUTE
@@ -4295,6 +4360,14 @@ init_pg_connection()
4295
4360
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4296
4361
  #endif
4297
4362
 
4363
+ #ifdef HAVE_PQENTERPIPELINEMODE
4364
+ rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4365
+ rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4366
+ rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4367
+ rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
4368
+ rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4369
+ #endif
4370
+
4298
4371
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
4299
4372
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
4300
4373
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");