pg 1.1.3 → 1.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) 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 +86 -0
  6. data/.github/workflows/source-gem.yml +129 -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 +210 -6
  16. data/Manifest.txt +3 -3
  17. data/README-Windows.rdoc +4 -4
  18. data/README.ja.rdoc +1 -2
  19. data/README.rdoc +51 -15
  20. data/Rakefile +31 -140
  21. data/Rakefile.cross +60 -56
  22. data/certs/ged.pem +24 -0
  23. data/certs/larskanis-2022.pem +26 -0
  24. data/ext/errorcodes.def +76 -0
  25. data/ext/errorcodes.txt +21 -2
  26. data/ext/extconf.rb +101 -26
  27. data/ext/gvl_wrappers.c +4 -0
  28. data/ext/gvl_wrappers.h +23 -0
  29. data/ext/pg.c +190 -98
  30. data/ext/pg.h +42 -17
  31. data/ext/pg_binary_decoder.c +20 -16
  32. data/ext/pg_binary_encoder.c +13 -12
  33. data/ext/pg_coder.c +95 -29
  34. data/ext/pg_connection.c +1043 -769
  35. data/ext/pg_copy_coder.c +50 -18
  36. data/ext/pg_record_coder.c +519 -0
  37. data/ext/pg_result.c +326 -142
  38. data/ext/pg_text_decoder.c +15 -9
  39. data/ext/pg_text_encoder.c +185 -53
  40. data/ext/pg_tuple.c +61 -27
  41. data/ext/pg_type_map.c +42 -9
  42. data/ext/pg_type_map_all_strings.c +19 -5
  43. data/ext/pg_type_map_by_class.c +54 -24
  44. data/ext/pg_type_map_by_column.c +73 -34
  45. data/ext/pg_type_map_by_mri_type.c +48 -19
  46. data/ext/pg_type_map_by_oid.c +55 -25
  47. data/ext/pg_type_map_in_ruby.c +51 -20
  48. data/ext/{util.c → pg_util.c} +7 -7
  49. data/ext/{util.h → pg_util.h} +0 -0
  50. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  51. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  52. data/lib/pg/basic_type_map_for_results.rb +81 -0
  53. data/lib/pg/basic_type_registry.rb +296 -0
  54. data/lib/pg/binary_decoder.rb +1 -0
  55. data/lib/pg/coder.rb +23 -2
  56. data/lib/pg/connection.rb +589 -59
  57. data/lib/pg/constants.rb +1 -0
  58. data/lib/pg/exceptions.rb +1 -0
  59. data/lib/pg/result.rb +13 -1
  60. data/lib/pg/text_decoder.rb +2 -3
  61. data/lib/pg/text_encoder.rb +8 -18
  62. data/lib/pg/type_map_by_column.rb +2 -1
  63. data/lib/pg/version.rb +4 -0
  64. data/lib/pg.rb +48 -33
  65. data/misc/openssl-pg-segfault.rb +31 -0
  66. data/misc/postgres/History.txt +9 -0
  67. data/misc/postgres/Manifest.txt +5 -0
  68. data/misc/postgres/README.txt +21 -0
  69. data/misc/postgres/Rakefile +21 -0
  70. data/misc/postgres/lib/postgres.rb +16 -0
  71. data/misc/ruby-pg/History.txt +9 -0
  72. data/misc/ruby-pg/Manifest.txt +5 -0
  73. data/misc/ruby-pg/README.txt +21 -0
  74. data/misc/ruby-pg/Rakefile +21 -0
  75. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  76. data/pg.gemspec +32 -0
  77. data/rakelib/task_extension.rb +46 -0
  78. data/sample/array_insert.rb +20 -0
  79. data/sample/async_api.rb +106 -0
  80. data/sample/async_copyto.rb +39 -0
  81. data/sample/async_mixed.rb +56 -0
  82. data/sample/check_conn.rb +21 -0
  83. data/sample/copydata.rb +71 -0
  84. data/sample/copyfrom.rb +81 -0
  85. data/sample/copyto.rb +19 -0
  86. data/sample/cursor.rb +21 -0
  87. data/sample/disk_usage_report.rb +177 -0
  88. data/sample/issue-119.rb +94 -0
  89. data/sample/losample.rb +69 -0
  90. data/sample/minimal-testcase.rb +17 -0
  91. data/sample/notify_wait.rb +72 -0
  92. data/sample/pg_statistics.rb +285 -0
  93. data/sample/replication_monitor.rb +222 -0
  94. data/sample/test_binary_values.rb +33 -0
  95. data/sample/wal_shipper.rb +434 -0
  96. data/sample/warehouse_partitions.rb +311 -0
  97. data.tar.gz.sig +0 -0
  98. metadata +94 -237
  99. metadata.gz.sig +0 -0
  100. data/ChangeLog +0 -6595
  101. data/lib/pg/basic_type_mapping.rb +0 -459
  102. data/spec/data/expected_trace.out +0 -26
  103. data/spec/data/random_binary_data +0 -0
  104. data/spec/helpers.rb +0 -381
  105. data/spec/pg/basic_type_mapping_spec.rb +0 -508
  106. data/spec/pg/connection_spec.rb +0 -1849
  107. data/spec/pg/connection_sync_spec.rb +0 -41
  108. data/spec/pg/result_spec.rb +0 -491
  109. data/spec/pg/tuple_spec.rb +0 -280
  110. data/spec/pg/type_map_by_class_spec.rb +0 -138
  111. data/spec/pg/type_map_by_column_spec.rb +0 -222
  112. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  113. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  114. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  115. data/spec/pg/type_map_spec.rb +0 -22
  116. data/spec/pg/type_spec.rb +0 -949
  117. data/spec/pg_spec.rb +0 -50
data/ext/pg_connection.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_connection.c - PG::Connection class extension
3
- * $Id: pg_connection.c,v b49f54dc755b 2018/09/01 12:52:41 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -12,14 +12,18 @@
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;
17
+ static VALUE sym_symbol, sym_string, sym_static_symbol;
16
18
 
17
19
  static PQnoticeReceiver default_notice_receiver = NULL;
18
20
  static PQnoticeProcessor default_notice_processor = NULL;
19
21
 
20
22
  static VALUE pgconn_finish( VALUE );
21
23
  static VALUE pgconn_set_default_encoding( VALUE self );
22
- void pgconn_set_internal_encoding_index( VALUE );
24
+ static VALUE pgconn_wait_for_flush( VALUE self );
25
+ static void pgconn_set_internal_encoding_index( VALUE );
26
+ static const rb_data_type_t pg_connection_type;
23
27
 
24
28
  /*
25
29
  * Global functions
@@ -32,7 +36,7 @@ t_pg_connection *
32
36
  pg_get_connection( VALUE self )
33
37
  {
34
38
  t_pg_connection *this;
35
- Data_Get_Struct( self, t_pg_connection, this);
39
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
36
40
 
37
41
  return this;
38
42
  }
@@ -45,7 +49,7 @@ static t_pg_connection *
45
49
  pg_get_connection_safe( VALUE self )
46
50
  {
47
51
  t_pg_connection *this;
48
- Data_Get_Struct( self, t_pg_connection, this);
52
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
49
53
 
50
54
  if ( !this->pgconn )
51
55
  rb_raise( rb_eConnectionBad, "connection is closed" );
@@ -64,7 +68,7 @@ PGconn *
64
68
  pg_get_pgconn( VALUE self )
65
69
  {
66
70
  t_pg_connection *this;
67
- Data_Get_Struct( self, t_pg_connection, this);
71
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
68
72
 
69
73
  if ( !this->pgconn )
70
74
  rb_raise( rb_eConnectionBad, "connection is closed" );
@@ -85,8 +89,7 @@ pgconn_close_socket_io( VALUE self )
85
89
 
86
90
  if ( RTEST(socket_io) ) {
87
91
  #if defined(_WIN32)
88
- int ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
89
- if( rb_w32_unwrap_io_handle(ruby_sd) ){
92
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
90
93
  rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
91
94
  }
92
95
  #endif
@@ -145,17 +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->external_encoding );
157
- rb_gc_mark( this->encoder_for_put_copy_data );
158
- 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 );
159
176
  }
160
177
 
161
178
 
@@ -163,14 +180,45 @@ pgconn_gc_mark( t_pg_connection *this )
163
180
  * GC Free function
164
181
  */
165
182
  static void
166
- pgconn_gc_free( t_pg_connection *this )
183
+ pgconn_gc_free( void *_this )
167
184
  {
185
+ t_pg_connection *this = (t_pg_connection *)_this;
186
+ #if defined(_WIN32)
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
+ }
192
+ #endif
168
193
  if (this->pgconn != NULL)
169
194
  PQfinish( this->pgconn );
170
195
 
171
196
  xfree(this);
172
197
  }
173
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
+
174
222
 
175
223
  /**************************************************************************
176
224
  * Class Methods
@@ -186,7 +234,7 @@ static VALUE
186
234
  pgconn_s_allocate( VALUE klass )
187
235
  {
188
236
  t_pg_connection *this;
189
- 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 );
190
238
 
191
239
  this->pgconn = NULL;
192
240
  this->socket_io = Qnil;
@@ -197,76 +245,17 @@ pgconn_s_allocate( VALUE klass )
197
245
  this->encoder_for_put_copy_data = Qnil;
198
246
  this->decoder_for_get_copy_data = Qnil;
199
247
  this->trace_stream = Qnil;
200
- this->external_encoding = Qnil;
201
- this->guess_result_memsize = 1;
202
248
 
203
249
  return self;
204
250
  }
205
251
 
206
-
207
- /*
208
- * Document-method: new
209
- *
210
- * call-seq:
211
- * PG::Connection.new -> conn
212
- * PG::Connection.new(connection_hash) -> conn
213
- * PG::Connection.new(connection_string) -> conn
214
- * PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
215
- *
216
- * Create a connection to the specified server.
217
- *
218
- * [+host+]
219
- * server hostname
220
- * [+hostaddr+]
221
- * server address (avoids hostname lookup, overrides +host+)
222
- * [+port+]
223
- * server port number
224
- * [+dbname+]
225
- * connecting database name
226
- * [+user+]
227
- * login user name
228
- * [+password+]
229
- * login password
230
- * [+connect_timeout+]
231
- * maximum time to wait for connection to succeed
232
- * [+options+]
233
- * backend options
234
- * [+tty+]
235
- * (ignored in newer versions of PostgreSQL)
236
- * [+sslmode+]
237
- * (disable|allow|prefer|require)
238
- * [+krbsrvname+]
239
- * kerberos service name
240
- * [+gsslib+]
241
- * GSS library to use for GSSAPI authentication
242
- * [+service+]
243
- * service name to use for additional parameters
244
- *
245
- * Examples:
246
- *
247
- * # Connect using all defaults
248
- * PG::Connection.new
249
- *
250
- * # As a Hash
251
- * PG::Connection.new( :dbname => 'test', :port => 5432 )
252
- *
253
- * # As a String
254
- * PG::Connection.new( "dbname=test port=5432" )
255
- *
256
- * # As an Array
257
- * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
258
- *
259
- * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
260
- * connection will have its +client_encoding+ set accordingly.
261
- *
262
- * Raises a PG::Error if the connection fails.
263
- */
264
252
  static VALUE
265
- pgconn_init(int argc, VALUE *argv, VALUE self)
253
+ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
266
254
  {
267
255
  t_pg_connection *this;
268
256
  VALUE conninfo;
269
257
  VALUE error;
258
+ VALUE self = pgconn_s_allocate( klass );
270
259
 
271
260
  this = pg_get_connection( self );
272
261
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
@@ -295,14 +284,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
295
284
  * PG::Connection.connect_start(connection_string) -> conn
296
285
  * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
297
286
  *
298
- * This is an asynchronous version of PG::Connection.connect().
287
+ * This is an asynchronous version of PG::Connection.new.
299
288
  *
300
289
  * Use #connect_poll to poll the status of the connection.
301
290
  *
302
291
  * NOTE: this does *not* set the connection's +client_encoding+ for you if
303
- * Encoding.default_internal is set. To set it after the connection is established,
292
+ * +Encoding.default_internal+ is set. To set it after the connection is established,
304
293
  * call #internal_encoding=. You can also set it automatically by setting
305
- * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
294
+ * <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
295
+ *
296
+ * See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
306
297
  *
307
298
  */
308
299
  static VALUE
@@ -337,34 +328,14 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
337
328
  return rb_conn;
338
329
  }
339
330
 
340
- /*
341
- * call-seq:
342
- * PG::Connection.ping(connection_hash) -> Integer
343
- * PG::Connection.ping(connection_string) -> Integer
344
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
345
- *
346
- * Check server status.
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
- * Available since PostgreSQL-9.1
359
- */
360
331
  static VALUE
361
- pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
332
+ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
362
333
  {
363
334
  PGPing ping;
364
335
  VALUE conninfo;
365
336
 
366
337
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
367
- ping = PQping( StringValueCStr(conninfo) );
338
+ ping = gvl_PQping( StringValueCStr(conninfo) );
368
339
 
369
340
  return INT2FIX((int)ping);
370
341
  }
@@ -407,29 +378,8 @@ pgconn_s_conndefaults(VALUE self)
407
378
 
408
379
 
409
380
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
410
- /*
411
- * call-seq:
412
- * conn.encrypt_password( password, username, algorithm=nil ) -> String
413
- *
414
- * This function is intended to be used by client applications that wish to send commands like <tt>ALTER USER joe PASSWORD 'pwd'</tt>.
415
- * 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.
416
- * Instead, use this function to convert the password to encrypted form before it is sent.
417
- *
418
- * The +password+ and +username+ arguments are the cleartext password, and the SQL name of the user it is for.
419
- * +algorithm+ specifies the encryption algorithm to use to encrypt the password.
420
- * 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).
421
- * Note that support for +scram-sha-256+ was introduced in PostgreSQL version 10, and will not work correctly with older server versions.
422
- * If algorithm is omitted or +nil+, this function will query the server for the current value of the +password_encryption+ setting.
423
- * That can block, and will fail if the current transaction is aborted, or if the connection is busy executing another query.
424
- * 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.
425
- *
426
- * Return value is the encrypted password.
427
- * The caller can assume the string doesn't contain any special characters that would require escaping.
428
- *
429
- * Available since PostgreSQL-10
430
- */
431
381
  static VALUE
432
- pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
382
+ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
433
383
  {
434
384
  char *encrypted = NULL;
435
385
  VALUE rval = Qnil;
@@ -445,10 +395,6 @@ pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
445
395
  if ( encrypted ) {
446
396
  rval = rb_str_new2( encrypted );
447
397
  PQfreemem( encrypted );
448
-
449
- OBJ_INFECT( rval, password );
450
- OBJ_INFECT( rval, username );
451
- OBJ_INFECT( rval, algorithm );
452
398
  } else {
453
399
  rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
454
400
  }
@@ -481,9 +427,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
481
427
  rval = rb_str_new2( encrypted );
482
428
  PQfreemem( encrypted );
483
429
 
484
- OBJ_INFECT( rval, password );
485
- OBJ_INFECT( rval, username );
486
-
487
430
  return rval;
488
431
  }
489
432
 
@@ -531,6 +474,11 @@ pgconn_connect_poll(VALUE self)
531
474
  {
532
475
  PostgresPollingStatusType status;
533
476
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
477
+
478
+ if ( status == PGRES_POLLING_FAILED ) {
479
+ pgconn_close_socket_io(self);
480
+ }
481
+
534
482
  return INT2FIX((int)status);
535
483
  }
536
484
 
@@ -567,15 +515,8 @@ pgconn_finished_p( VALUE self )
567
515
  }
568
516
 
569
517
 
570
- /*
571
- * call-seq:
572
- * conn.reset()
573
- *
574
- * Resets the backend connection. This method closes the
575
- * backend connection and tries to re-connect.
576
- */
577
518
  static VALUE
578
- pgconn_reset( VALUE self )
519
+ pgconn_sync_reset( VALUE self )
579
520
  {
580
521
  pgconn_close_socket_io( self );
581
522
  gvl_PQreset( pg_get_pgconn(self) );
@@ -614,6 +555,11 @@ pgconn_reset_poll(VALUE self)
614
555
  {
615
556
  PostgresPollingStatusType status;
616
557
  status = gvl_PQresetPoll(pg_get_pgconn(self));
558
+
559
+ if ( status == PGRES_POLLING_FAILED ) {
560
+ pgconn_close_socket_io(self);
561
+ }
562
+
617
563
  return INT2FIX((int)status);
618
564
  }
619
565
 
@@ -629,7 +575,7 @@ pgconn_db(VALUE self)
629
575
  {
630
576
  char *db = PQdb(pg_get_pgconn(self));
631
577
  if (!db) return Qnil;
632
- return rb_tainted_str_new2(db);
578
+ return rb_str_new2(db);
633
579
  }
634
580
 
635
581
  /*
@@ -643,7 +589,7 @@ pgconn_user(VALUE self)
643
589
  {
644
590
  char *user = PQuser(pg_get_pgconn(self));
645
591
  if (!user) return Qnil;
646
- return rb_tainted_str_new2(user);
592
+ return rb_str_new2(user);
647
593
  }
648
594
 
649
595
  /*
@@ -657,7 +603,7 @@ pgconn_pass(VALUE self)
657
603
  {
658
604
  char *user = PQpass(pg_get_pgconn(self));
659
605
  if (!user) return Qnil;
660
- return rb_tainted_str_new2(user);
606
+ return rb_str_new2(user);
661
607
  }
662
608
 
663
609
  /*
@@ -671,7 +617,7 @@ pgconn_host(VALUE self)
671
617
  {
672
618
  char *host = PQhost(pg_get_pgconn(self));
673
619
  if (!host) return Qnil;
674
- return rb_tainted_str_new2(host);
620
+ return rb_str_new2(host);
675
621
  }
676
622
 
677
623
  /*
@@ -684,21 +630,19 @@ static VALUE
684
630
  pgconn_port(VALUE self)
685
631
  {
686
632
  char* port = PQport(pg_get_pgconn(self));
687
- return INT2NUM(atol(port));
633
+ return INT2NUM(atoi(port));
688
634
  }
689
635
 
690
636
  /*
691
637
  * call-seq:
692
638
  * conn.tty()
693
639
  *
694
- * Returns the connected pgtty. (Obsolete)
640
+ * Obsolete function.
695
641
  */
696
642
  static VALUE
697
643
  pgconn_tty(VALUE self)
698
644
  {
699
- char *tty = PQtty(pg_get_pgconn(self));
700
- if (!tty) return Qnil;
701
- return rb_tainted_str_new2(tty);
645
+ return rb_str_new2("");
702
646
  }
703
647
 
704
648
  /*
@@ -712,11 +656,10 @@ pgconn_options(VALUE self)
712
656
  {
713
657
  char *options = PQoptions(pg_get_pgconn(self));
714
658
  if (!options) return Qnil;
715
- return rb_tainted_str_new2(options);
659
+ return rb_str_new2(options);
716
660
  }
717
661
 
718
662
 
719
- #ifdef HAVE_PQCONNINFO
720
663
  /*
721
664
  * call-seq:
722
665
  * conn.conninfo -> hash
@@ -736,14 +679,17 @@ pgconn_conninfo( VALUE self )
736
679
 
737
680
  return array;
738
681
  }
739
- #endif
740
682
 
741
683
 
742
684
  /*
743
685
  * call-seq:
744
686
  * conn.status()
745
687
  *
746
- * 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_*
747
693
  */
748
694
  static VALUE
749
695
  pgconn_status(VALUE self)
@@ -793,7 +739,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
793
739
  if(ret == NULL)
794
740
  return Qnil;
795
741
  else
796
- return rb_tainted_str_new2(ret);
742
+ return rb_str_new2(ret);
797
743
  }
798
744
 
799
745
  /*
@@ -831,14 +777,17 @@ pgconn_server_version(VALUE self)
831
777
  * call-seq:
832
778
  * conn.error_message -> String
833
779
  *
834
- * 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.
835
784
  */
836
785
  static VALUE
837
786
  pgconn_error_message(VALUE self)
838
787
  {
839
788
  char *error = PQerrorMessage(pg_get_pgconn(self));
840
789
  if (!error) return Qnil;
841
- return rb_tainted_str_new2(error);
790
+ return rb_str_new2(error);
842
791
  }
843
792
 
844
793
  /*
@@ -862,6 +811,8 @@ static VALUE
862
811
  pgconn_socket(VALUE self)
863
812
  {
864
813
  int sd;
814
+ pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
815
+
865
816
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
866
817
  rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
867
818
  return INT2NUM(sd);
@@ -884,8 +835,8 @@ pgconn_socket_io(VALUE self)
884
835
  {
885
836
  int sd;
886
837
  int ruby_sd;
887
- ID id_autoclose = rb_intern("autoclose=");
888
838
  t_pg_connection *this = pg_get_connection_safe( self );
839
+ VALUE cSocket;
889
840
  VALUE socket_io = this->socket_io;
890
841
 
891
842
  if ( !RTEST(socket_io) ) {
@@ -894,14 +845,19 @@ pgconn_socket_io(VALUE self)
894
845
 
895
846
  #ifdef _WIN32
896
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
+ }
851
+ this->ruby_sd = ruby_sd;
897
852
  #else
898
853
  ruby_sd = sd;
899
854
  #endif
900
855
 
901
- 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));
902
858
 
903
859
  /* Disable autoclose feature */
904
- rb_funcall( socket_io, id_autoclose, 1, Qfalse );
860
+ rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
905
861
 
906
862
  this->socket_io = socket_io;
907
863
  }
@@ -923,6 +879,51 @@ pgconn_backend_pid(VALUE self)
923
879
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
924
880
  }
925
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
+
926
927
  /*
927
928
  * call-seq:
928
929
  * conn.connection_needs_password() -> Boolean
@@ -953,36 +954,27 @@ pgconn_connection_used_password(VALUE self)
953
954
  /* :TODO: get_ssl */
954
955
 
955
956
 
956
- static VALUE pgconn_exec_params( int, VALUE *, VALUE );
957
+ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
957
958
 
958
959
  /*
959
960
  * call-seq:
960
- * conn.exec(sql) -> PG::Result
961
- * conn.exec(sql) {|pg_result| block }
962
- *
963
- * Sends SQL query request specified by _sql_ to PostgreSQL.
964
- * Returns a PG::Result instance on success.
965
- * On failure, it raises a PG::Error.
961
+ * conn.sync_exec(sql) -> PG::Result
962
+ * conn.sync_exec(sql) {|pg_result| block }
966
963
  *
967
- * For backward compatibility, if you pass more than one parameter to this method,
968
- * it will call #exec_params for you. New code should explicitly use #exec_params if
969
- * argument placeholders are used.
964
+ * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
965
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
970
966
  *
971
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
972
- * and the PG::Result object will automatically be cleared when the block terminates.
973
- * In this instance, <code>conn.exec</code> returns the value of the block.
967
+ * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
968
+ * However #async_exec has two advantages:
974
969
  *
975
- * #sync_exec is implemented on the synchronous command processing API of libpq, whereas
976
- * #async_exec is implemented on the asynchronous API.
977
- * #sync_exec is somewhat faster that #async_exec, but blocks any signals to be processed until
978
- * the query is finished. This is most notably visible by a delayed reaction to Control+C.
979
- * Both methods ensure that other threads can process while waiting for the server to
980
- * complete the request.
970
+ * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
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.
981
973
  */
982
974
  static VALUE
983
- pgconn_exec(int argc, VALUE *argv, VALUE self)
975
+ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
984
976
  {
985
- PGconn *conn = pg_get_pgconn(self);
977
+ t_pg_connection *this = pg_get_connection_safe( self );
986
978
  PGresult *result = NULL;
987
979
  VALUE rb_pgresult;
988
980
 
@@ -990,7 +982,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
990
982
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
991
983
  VALUE query_str = argv[0];
992
984
 
993
- result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
985
+ result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
994
986
  rb_pgresult = pg_new_result(result, self);
995
987
  pg_result_check(rb_pgresult);
996
988
  if (rb_block_given_p()) {
@@ -1001,7 +993,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
1001
993
  pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
1002
994
 
1003
995
  /* Otherwise, just call #exec_params instead for backward-compatibility */
1004
- return pgconn_exec_params( argc, argv, self );
996
+ return pgconn_sync_exec_params( argc, argv, self );
1005
997
 
1006
998
  }
1007
999
 
@@ -1033,7 +1025,7 @@ struct query_params_data {
1033
1025
  * Filled by alloc_query_params()
1034
1026
  */
1035
1027
 
1036
- /* Wraps the pointer of allocated memory, if function parameters dont't
1028
+ /* Wraps the pointer of allocated memory, if function parameters don't
1037
1029
  * fit in the memory_pool below.
1038
1030
  */
1039
1031
  VALUE heap_pool;
@@ -1051,7 +1043,7 @@ struct query_params_data {
1051
1043
  Oid *types;
1052
1044
 
1053
1045
  /* This array takes the string values for the timeframe of the query,
1054
- * if param value convertion is required
1046
+ * if param value conversion is required
1055
1047
  */
1056
1048
  VALUE gc_array;
1057
1049
 
@@ -1065,8 +1057,9 @@ struct query_params_data {
1065
1057
  };
1066
1058
 
1067
1059
  static void
1068
- free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1060
+ free_typecast_heap_chain(void *_chain_entry)
1069
1061
  {
1062
+ struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
1070
1063
  while(chain_entry){
1071
1064
  struct linked_typecast_data *next = chain_entry->next;
1072
1065
  xfree(chain_entry);
@@ -1074,6 +1067,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1074
1067
  }
1075
1068
  }
1076
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
+
1077
1082
  static char *
1078
1083
  alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1079
1084
  {
@@ -1084,17 +1089,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1084
1089
  /* Did we already wrap a memory chain per T_DATA object? */
1085
1090
  if( NIL_P( *typecast_heap_chain ) ){
1086
1091
  /* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
1087
- *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 );
1088
1093
  allocated->next = NULL;
1089
1094
  } else {
1090
1095
  /* Append to the chain */
1091
- allocated->next = DATA_PTR( *typecast_heap_chain );
1092
- DATA_PTR( *typecast_heap_chain ) = allocated;
1096
+ allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
1097
+ RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
1093
1098
  }
1094
1099
 
1095
1100
  return &allocated->data[0];
1096
1101
  }
1097
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
+ };
1098
1114
 
1099
1115
  static int
1100
1116
  alloc_query_params(struct query_params_data *paramsData)
@@ -1109,7 +1125,7 @@ alloc_query_params(struct query_params_data *paramsData)
1109
1125
 
1110
1126
  Check_Type(paramsData->params, T_ARRAY);
1111
1127
 
1112
- p_typemap = DATA_PTR( paramsData->typemap );
1128
+ p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
1113
1129
  p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
1114
1130
 
1115
1131
  paramsData->heap_pool = Qnil;
@@ -1128,7 +1144,7 @@ alloc_query_params(struct query_params_data *paramsData)
1128
1144
  /* Allocate one combined memory pool for all possible function parameters */
1129
1145
  memory_pool = (char*)xmalloc( required_pool_size );
1130
1146
  /* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
1131
- 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 );
1132
1148
  required_pool_size = 0;
1133
1149
  }else{
1134
1150
  /* Use stack memory for function parameters */
@@ -1241,68 +1257,33 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1241
1257
  /* Use default typemap for queries. It's type is checked when assigned. */
1242
1258
  paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
1243
1259
  }else{
1260
+ t_typemap *tm;
1261
+ UNUSED(tm);
1262
+
1244
1263
  /* Check type of method param */
1245
- if ( !rb_obj_is_kind_of(paramsData->typemap, rb_cTypeMap) ) {
1246
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1247
- rb_obj_classname( paramsData->typemap ) );
1248
- }
1249
- Check_Type( paramsData->typemap, T_DATA );
1264
+ TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
1250
1265
  }
1251
1266
  }
1252
1267
 
1253
1268
  /*
1254
1269
  * call-seq:
1255
- * conn.exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1256
- * conn.exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1257
- *
1258
- * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
1259
- * for parameters.
1260
- *
1261
- * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
1262
- *
1263
- * +params+ is an array of the bind parameters for the SQL query.
1264
- * Each element of the +params+ array may be either:
1265
- * a hash of the form:
1266
- * {:value => String (value of bind parameter)
1267
- * :type => Integer (oid of type of bind parameter)
1268
- * :format => Integer (0 for text, 1 for binary)
1269
- * }
1270
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1271
- * { :value => <string value>, :type => 0, :format => 0 }
1272
- *
1273
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1274
- * inside the SQL query. The 0th element of the +params+ array is bound
1275
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1276
- *
1277
- * If the types are not specified, they will be inferred by PostgreSQL.
1278
- * Instead of specifying type oids, it's recommended to simply add
1279
- * explicit casts in the query to ensure that the right type is used.
1280
- *
1281
- * For example: "SELECT $1::int"
1282
- *
1283
- * The optional +result_format+ should be 0 for text results, 1
1284
- * for binary.
1270
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1271
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1285
1272
  *
1286
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1287
- * This will type cast the params from various Ruby types before transmission
1288
- * based on the encoders defined by the type map. When a type encoder is used
1289
- * the format and oid of a given bind parameter are retrieved from the encoder
1290
- * instead out of the hash form described above.
1291
- *
1292
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1293
- * and the PG::Result object will automatically be cleared when the block terminates.
1294
- * In this instance, <code>conn.exec</code> returns the value of the block.
1273
+ * This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
1274
+ * See #async_exec for the differences between the two API variants.
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.
1295
1276
  */
1296
1277
  static VALUE
1297
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1278
+ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1298
1279
  {
1299
- PGconn *conn = pg_get_pgconn(self);
1280
+ t_pg_connection *this = pg_get_connection_safe( self );
1300
1281
  PGresult *result = NULL;
1301
1282
  VALUE rb_pgresult;
1302
1283
  VALUE command, in_res_fmt;
1303
1284
  int nParams;
1304
1285
  int resultFormat;
1305
- struct query_params_data paramsData = { ENCODING_GET(self) };
1286
+ struct query_params_data paramsData = { this->enc_idx };
1306
1287
 
1307
1288
  /* For compatibility we accept 1 to 4 parameters */
1308
1289
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
@@ -1314,14 +1295,14 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1314
1295
  */
1315
1296
  if ( NIL_P(paramsData.params) ) {
1316
1297
  pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1317
- return pgconn_exec( 1, argv, self );
1298
+ return pgconn_sync_exec( 1, argv, self );
1318
1299
  }
1319
1300
  pgconn_query_assign_typemap( self, &paramsData );
1320
1301
 
1321
1302
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1322
1303
  nParams = alloc_query_params( &paramsData );
1323
1304
 
1324
- result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1305
+ result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1325
1306
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1326
1307
 
1327
1308
  free_query_params( &paramsData );
@@ -1338,28 +1319,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1338
1319
 
1339
1320
  /*
1340
1321
  * call-seq:
1341
- * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1342
- *
1343
- * Prepares statement _sql_ with name _name_ to be executed later.
1344
- * Returns a PG::Result instance on success.
1345
- * On failure, it raises a PG::Error.
1322
+ * conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1346
1323
  *
1347
- * +param_types+ is an optional parameter to specify the Oids of the
1348
- * types of the parameters.
1349
- *
1350
- * If the types are not specified, they will be inferred by PostgreSQL.
1351
- * Instead of specifying type oids, it's recommended to simply add
1352
- * explicit casts in the query to ensure that the right type is used.
1353
- *
1354
- * For example: "SELECT $1::int"
1355
- *
1356
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1357
- * inside the SQL query.
1324
+ * This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
1325
+ * See #async_exec for the differences between the two API variants.
1326
+ * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1358
1327
  */
1359
1328
  static VALUE
1360
- pgconn_prepare(int argc, VALUE *argv, VALUE self)
1329
+ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1361
1330
  {
1362
- PGconn *conn = pg_get_pgconn(self);
1331
+ t_pg_connection *this = pg_get_connection_safe( self );
1363
1332
  PGresult *result = NULL;
1364
1333
  VALUE rb_pgresult;
1365
1334
  VALUE name, command, in_paramtypes;
@@ -1369,7 +1338,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1369
1338
  Oid *paramTypes = NULL;
1370
1339
  const char *name_cstr;
1371
1340
  const char *command_cstr;
1372
- int enc_idx = ENCODING_GET(self);
1341
+ int enc_idx = this->enc_idx;
1373
1342
 
1374
1343
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1375
1344
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1387,7 +1356,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1387
1356
  paramTypes[i] = NUM2UINT(param);
1388
1357
  }
1389
1358
  }
1390
- result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1359
+ result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1391
1360
 
1392
1361
  xfree(paramTypes);
1393
1362
 
@@ -1398,49 +1367,23 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1398
1367
 
1399
1368
  /*
1400
1369
  * call-seq:
1401
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1402
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1403
- *
1404
- * Execute prepared named statement specified by _statement_name_.
1405
- * Returns a PG::Result instance on success.
1406
- * On failure, it raises a PG::Error.
1407
- *
1408
- * +params+ is an array of the optional bind parameters for the
1409
- * SQL query. Each element of the +params+ array may be either:
1410
- * a hash of the form:
1411
- * {:value => String (value of bind parameter)
1412
- * :format => Integer (0 for text, 1 for binary)
1413
- * }
1414
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1415
- * { :value => <string value>, :format => 0 }
1416
- *
1417
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1418
- * inside the SQL query. The 0th element of the +params+ array is bound
1419
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1420
- *
1421
- * The optional +result_format+ should be 0 for text results, 1
1422
- * for binary.
1423
- *
1424
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1425
- * This will type cast the params from various Ruby types before transmission
1426
- * based on the encoders defined by the type map. When a type encoder is used
1427
- * the format and oid of a given bind parameter are retrieved from the encoder
1428
- * instead out of the hash form described above.
1370
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1371
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1429
1372
  *
1430
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1431
- * and the PG::Result object will automatically be cleared when the block terminates.
1432
- * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
1373
+ * This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
1374
+ * See #async_exec for the differences between the two API variants.
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.
1433
1376
  */
1434
1377
  static VALUE
1435
- pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1378
+ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1436
1379
  {
1437
- PGconn *conn = pg_get_pgconn(self);
1380
+ t_pg_connection *this = pg_get_connection_safe( self );
1438
1381
  PGresult *result = NULL;
1439
1382
  VALUE rb_pgresult;
1440
1383
  VALUE name, in_res_fmt;
1441
1384
  int nParams;
1442
1385
  int resultFormat;
1443
- struct query_params_data paramsData = { ENCODING_GET(self) };
1386
+ struct query_params_data paramsData = { this->enc_idx };
1444
1387
 
1445
1388
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1446
1389
  paramsData.with_types = 0;
@@ -1453,7 +1396,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1453
1396
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1454
1397
  nParams = alloc_query_params( &paramsData );
1455
1398
 
1456
- result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1399
+ result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1457
1400
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1458
1401
  resultFormat);
1459
1402
 
@@ -1470,25 +1413,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1470
1413
 
1471
1414
  /*
1472
1415
  * call-seq:
1473
- * conn.describe_prepared( statement_name ) -> PG::Result
1416
+ * conn.sync_describe_prepared( statement_name ) -> PG::Result
1474
1417
  *
1475
- * Retrieve information about the prepared statement
1476
- * _statement_name_.
1418
+ * This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
1419
+ * See #async_exec for the differences between the two API variants.
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.
1477
1421
  */
1478
1422
  static VALUE
1479
- pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1423
+ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1480
1424
  {
1481
1425
  PGresult *result;
1482
1426
  VALUE rb_pgresult;
1483
- PGconn *conn = pg_get_pgconn(self);
1427
+ t_pg_connection *this = pg_get_connection_safe( self );
1484
1428
  const char *stmt;
1485
1429
  if(NIL_P(stmt_name)) {
1486
1430
  stmt = NULL;
1487
1431
  }
1488
1432
  else {
1489
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1433
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1490
1434
  }
1491
- result = gvl_PQdescribePrepared(conn, stmt);
1435
+ result = gvl_PQdescribePrepared(this->pgconn, stmt);
1492
1436
  rb_pgresult = pg_new_result(result, self);
1493
1437
  pg_result_check(rb_pgresult);
1494
1438
  return rb_pgresult;
@@ -1497,25 +1441,27 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1497
1441
 
1498
1442
  /*
1499
1443
  * call-seq:
1500
- * conn.describe_portal( portal_name ) -> PG::Result
1444
+ * conn.sync_describe_portal( portal_name ) -> PG::Result
1501
1445
  *
1502
- * Retrieve information about the portal _portal_name_.
1446
+ * This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
1447
+ * See #async_exec for the differences between the two API variants.
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.
1503
1449
  */
1504
1450
  static VALUE
1505
- pgconn_describe_portal(self, stmt_name)
1451
+ pgconn_sync_describe_portal(self, stmt_name)
1506
1452
  VALUE self, stmt_name;
1507
1453
  {
1508
1454
  PGresult *result;
1509
1455
  VALUE rb_pgresult;
1510
- PGconn *conn = pg_get_pgconn(self);
1456
+ t_pg_connection *this = pg_get_connection_safe( self );
1511
1457
  const char *stmt;
1512
1458
  if(NIL_P(stmt_name)) {
1513
1459
  stmt = NULL;
1514
1460
  }
1515
1461
  else {
1516
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1462
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1517
1463
  }
1518
- result = gvl_PQdescribePortal(conn, stmt);
1464
+ result = gvl_PQdescribePortal(this->pgconn, stmt);
1519
1465
  rb_pgresult = pg_new_result(result, self);
1520
1466
  pg_result_check(rb_pgresult);
1521
1467
  return rb_pgresult;
@@ -1537,6 +1483,9 @@ pgconn_describe_portal(self, stmt_name)
1537
1483
  * * +PGRES_NONFATAL_ERROR+
1538
1484
  * * +PGRES_FATAL_ERROR+
1539
1485
  * * +PGRES_COPY_BOTH+
1486
+ * * +PGRES_SINGLE_TUPLE+
1487
+ * * +PGRES_PIPELINE_SYNC+
1488
+ * * +PGRES_PIPELINE_ABORTED+
1540
1489
  */
1541
1490
  static VALUE
1542
1491
  pgconn_make_empty_pgresult(VALUE self, VALUE status)
@@ -1562,13 +1511,15 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1562
1511
  * Consider using exec_params, which avoids the need for passing values
1563
1512
  * inside of SQL commands.
1564
1513
  *
1565
- * Encoding of escaped string will be equal to client encoding of connection.
1514
+ * Character encoding of escaped string will be equal to client encoding of connection.
1566
1515
  *
1567
1516
  * NOTE: This class version of this method can only be used safely in client
1568
1517
  * programs that use a single PostgreSQL connection at a time (in this case it can
1569
1518
  * find out what it needs to know "behind the scenes"). It might give the wrong
1570
1519
  * results if used in programs that use multiple database connections; use the
1571
1520
  * same method on the connection object in such cases.
1521
+ *
1522
+ * See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
1572
1523
  */
1573
1524
  static VALUE
1574
1525
  pgconn_s_escape(VALUE self, VALUE string)
@@ -1580,7 +1531,7 @@ pgconn_s_escape(VALUE self, VALUE string)
1580
1531
  int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1581
1532
 
1582
1533
  StringValueCStr(string);
1583
- enc_idx = ENCODING_GET( singleton ? string : self );
1534
+ enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
1584
1535
  if( ENCODING_GET(string) != enc_idx ){
1585
1536
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1586
1537
  }
@@ -1597,7 +1548,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1597
1548
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1598
1549
  }
1599
1550
  rb_str_set_len(result, size);
1600
- OBJ_INFECT(result, string);
1601
1551
 
1602
1552
  return result;
1603
1553
  }
@@ -1643,7 +1593,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1643
1593
  }
1644
1594
 
1645
1595
  ret = rb_str_new((char*)to, to_len - 1);
1646
- OBJ_INFECT(ret, str);
1647
1596
  PQfreemem(to);
1648
1597
  return ret;
1649
1598
  }
@@ -1673,7 +1622,6 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1673
1622
  to = PQunescapeBytea(from, &to_len);
1674
1623
 
1675
1624
  ret = rb_str_new((char*)to, to_len);
1676
- OBJ_INFECT(ret, str);
1677
1625
  PQfreemem(to);
1678
1626
  return ret;
1679
1627
  }
@@ -1684,33 +1632,32 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1684
1632
  *
1685
1633
  * Escape an arbitrary String +str+ as a literal.
1686
1634
  *
1687
- * Available since PostgreSQL-9.0
1635
+ * See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
1688
1636
  */
1689
1637
  static VALUE
1690
1638
  pgconn_escape_literal(VALUE self, VALUE string)
1691
1639
  {
1692
- PGconn *conn = pg_get_pgconn(self);
1640
+ t_pg_connection *this = pg_get_connection_safe( self );
1693
1641
  char *escaped = NULL;
1694
1642
  VALUE error;
1695
1643
  VALUE result = Qnil;
1696
- int enc_idx = ENCODING_GET(self);
1644
+ int enc_idx = this->enc_idx;
1697
1645
 
1698
1646
  StringValueCStr(string);
1699
1647
  if( ENCODING_GET(string) != enc_idx ){
1700
1648
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1701
1649
  }
1702
1650
 
1703
- escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1651
+ escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1704
1652
  if (escaped == NULL)
1705
1653
  {
1706
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1654
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1707
1655
  rb_iv_set(error, "@connection", self);
1708
1656
  rb_exc_raise(error);
1709
1657
  return Qnil;
1710
1658
  }
1711
1659
  result = rb_str_new2(escaped);
1712
1660
  PQfreemem(escaped);
1713
- OBJ_INFECT(result, string);
1714
1661
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1715
1662
 
1716
1663
  return result;
@@ -1725,34 +1672,31 @@ pgconn_escape_literal(VALUE self, VALUE string)
1725
1672
  * This method does the same as #quote_ident with a String argument,
1726
1673
  * but it doesn't support an Array argument and it makes use of libpq
1727
1674
  * to process the string.
1728
- *
1729
- * Available since PostgreSQL-9.0
1730
1675
  */
1731
1676
  static VALUE
1732
1677
  pgconn_escape_identifier(VALUE self, VALUE string)
1733
1678
  {
1734
- PGconn *conn = pg_get_pgconn(self);
1679
+ t_pg_connection *this = pg_get_connection_safe( self );
1735
1680
  char *escaped = NULL;
1736
1681
  VALUE error;
1737
1682
  VALUE result = Qnil;
1738
- int enc_idx = ENCODING_GET(self);
1683
+ int enc_idx = this->enc_idx;
1739
1684
 
1740
1685
  StringValueCStr(string);
1741
1686
  if( ENCODING_GET(string) != enc_idx ){
1742
1687
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1743
1688
  }
1744
1689
 
1745
- escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1690
+ escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1746
1691
  if (escaped == NULL)
1747
1692
  {
1748
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1693
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1749
1694
  rb_iv_set(error, "@connection", self);
1750
1695
  rb_exc_raise(error);
1751
1696
  return Qnil;
1752
1697
  }
1753
1698
  result = rb_str_new2(escaped);
1754
1699
  PQfreemem(escaped);
1755
- OBJ_INFECT(result, string);
1756
1700
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1757
1701
 
1758
1702
  return result;
@@ -1793,8 +1737,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1793
1737
  * # do something with the received row
1794
1738
  * end
1795
1739
  * end
1796
- *
1797
- * Available since PostgreSQL-9.2
1798
1740
  */
1799
1741
  static VALUE
1800
1742
  pgconn_set_single_row_mode(VALUE self)
@@ -1830,16 +1772,17 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1830
1772
  static VALUE
1831
1773
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1832
1774
  {
1833
- PGconn *conn = pg_get_pgconn(self);
1775
+ t_pg_connection *this = pg_get_connection_safe( self );
1834
1776
  VALUE error;
1835
1777
 
1836
1778
  /* If called with no or nil parameters, use PQexec for compatibility */
1837
1779
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1838
- if(gvl_PQsendQuery(conn, pg_cstr_enc(argv[0], ENCODING_GET(self))) == 0) {
1839
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1780
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1781
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1840
1782
  rb_iv_set(error, "@connection", self);
1841
1783
  rb_exc_raise(error);
1842
1784
  }
1785
+ pgconn_wait_for_flush( self );
1843
1786
  return Qnil;
1844
1787
  }
1845
1788
 
@@ -1869,7 +1812,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1869
1812
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1870
1813
  * { :value => <string value>, :type => 0, :format => 0 }
1871
1814
  *
1872
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1815
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1873
1816
  * inside the SQL query. The 0th element of the +params+ array is bound
1874
1817
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1875
1818
  *
@@ -1882,7 +1825,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1882
1825
  * The optional +result_format+ should be 0 for text results, 1
1883
1826
  * for binary.
1884
1827
  *
1885
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1828
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1886
1829
  * This will type cast the params from various Ruby types before transmission
1887
1830
  * based on the encoders defined by the type map. When a type encoder is used
1888
1831
  * the format and oid of a given bind parameter are retrieved from the encoder
@@ -1892,13 +1835,13 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1892
1835
  static VALUE
1893
1836
  pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1894
1837
  {
1895
- PGconn *conn = pg_get_pgconn(self);
1838
+ t_pg_connection *this = pg_get_connection_safe( self );
1896
1839
  int result;
1897
1840
  VALUE command, in_res_fmt;
1898
1841
  VALUE error;
1899
1842
  int nParams;
1900
1843
  int resultFormat;
1901
- struct query_params_data paramsData = { ENCODING_GET(self) };
1844
+ struct query_params_data paramsData = { this->enc_idx };
1902
1845
 
1903
1846
  rb_scan_args(argc, argv, "22", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1904
1847
  paramsData.with_types = 1;
@@ -1907,16 +1850,17 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1907
1850
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1908
1851
  nParams = alloc_query_params( &paramsData );
1909
1852
 
1910
- result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1853
+ result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1911
1854
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1912
1855
 
1913
1856
  free_query_params( &paramsData );
1914
1857
 
1915
1858
  if(result == 0) {
1916
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1859
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1917
1860
  rb_iv_set(error, "@connection", self);
1918
1861
  rb_exc_raise(error);
1919
1862
  }
1863
+ pgconn_wait_for_flush( self );
1920
1864
  return Qnil;
1921
1865
  }
1922
1866
 
@@ -1937,13 +1881,13 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1937
1881
  *
1938
1882
  * For example: "SELECT $1::int"
1939
1883
  *
1940
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1884
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1941
1885
  * inside the SQL query.
1942
1886
  */
1943
1887
  static VALUE
1944
1888
  pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1945
1889
  {
1946
- PGconn *conn = pg_get_pgconn(self);
1890
+ t_pg_connection *this = pg_get_connection_safe( self );
1947
1891
  int result;
1948
1892
  VALUE name, command, in_paramtypes;
1949
1893
  VALUE param;
@@ -1953,7 +1897,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1953
1897
  Oid *paramTypes = NULL;
1954
1898
  const char *name_cstr;
1955
1899
  const char *command_cstr;
1956
- int enc_idx = ENCODING_GET(self);
1900
+ int enc_idx = this->enc_idx;
1957
1901
 
1958
1902
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1959
1903
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1971,15 +1915,16 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1971
1915
  paramTypes[i] = NUM2UINT(param);
1972
1916
  }
1973
1917
  }
1974
- result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1918
+ result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1975
1919
 
1976
1920
  xfree(paramTypes);
1977
1921
 
1978
1922
  if(result == 0) {
1979
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1923
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1980
1924
  rb_iv_set(error, "@connection", self);
1981
1925
  rb_exc_raise(error);
1982
1926
  }
1927
+ pgconn_wait_for_flush( self );
1983
1928
  return Qnil;
1984
1929
  }
1985
1930
 
@@ -2001,14 +1946,14 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2001
1946
  * or, it may be a String. If it is a string, that is equivalent to the hash:
2002
1947
  * { :value => <string value>, :format => 0 }
2003
1948
  *
2004
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1949
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
2005
1950
  * inside the SQL query. The 0th element of the +params+ array is bound
2006
1951
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
2007
1952
  *
2008
1953
  * The optional +result_format+ should be 0 for text results, 1
2009
1954
  * for binary.
2010
1955
  *
2011
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1956
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
2012
1957
  * This will type cast the params from various Ruby types before transmission
2013
1958
  * based on the encoders defined by the type map. When a type encoder is used
2014
1959
  * the format and oid of a given bind parameter are retrieved from the encoder
@@ -2018,37 +1963,37 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2018
1963
  static VALUE
2019
1964
  pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2020
1965
  {
2021
- PGconn *conn = pg_get_pgconn(self);
1966
+ t_pg_connection *this = pg_get_connection_safe( self );
2022
1967
  int result;
2023
1968
  VALUE name, in_res_fmt;
2024
1969
  VALUE error;
2025
1970
  int nParams;
2026
1971
  int resultFormat;
2027
- struct query_params_data paramsData = { ENCODING_GET(self) };
1972
+ struct query_params_data paramsData = { this->enc_idx };
2028
1973
 
2029
1974
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
2030
1975
  paramsData.with_types = 0;
2031
1976
 
2032
1977
  if(NIL_P(paramsData.params)) {
2033
1978
  paramsData.params = rb_ary_new2(0);
2034
- resultFormat = 0;
2035
1979
  }
2036
1980
  pgconn_query_assign_typemap( self, &paramsData );
2037
1981
 
2038
1982
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
2039
1983
  nParams = alloc_query_params( &paramsData );
2040
1984
 
2041
- result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1985
+ result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
2042
1986
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
2043
1987
  resultFormat);
2044
1988
 
2045
1989
  free_query_params( &paramsData );
2046
1990
 
2047
1991
  if(result == 0) {
2048
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1992
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2049
1993
  rb_iv_set(error, "@connection", self);
2050
1994
  rb_exc_raise(error);
2051
1995
  }
1996
+ pgconn_wait_for_flush( self );
2052
1997
  return Qnil;
2053
1998
  }
2054
1999
 
@@ -2063,13 +2008,14 @@ static VALUE
2063
2008
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2064
2009
  {
2065
2010
  VALUE error;
2066
- PGconn *conn = pg_get_pgconn(self);
2011
+ t_pg_connection *this = pg_get_connection_safe( self );
2067
2012
  /* returns 0 on failure */
2068
- if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
2069
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2013
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
2014
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2070
2015
  rb_iv_set(error, "@connection", self);
2071
2016
  rb_exc_raise(error);
2072
2017
  }
2018
+ pgconn_wait_for_flush( self );
2073
2019
  return Qnil;
2074
2020
  }
2075
2021
 
@@ -2085,35 +2031,20 @@ static VALUE
2085
2031
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2086
2032
  {
2087
2033
  VALUE error;
2088
- PGconn *conn = pg_get_pgconn(self);
2034
+ t_pg_connection *this = pg_get_connection_safe( self );
2089
2035
  /* returns 0 on failure */
2090
- if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
2091
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2036
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2037
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2092
2038
  rb_iv_set(error, "@connection", self);
2093
2039
  rb_exc_raise(error);
2094
2040
  }
2041
+ pgconn_wait_for_flush( self );
2095
2042
  return Qnil;
2096
2043
  }
2097
2044
 
2098
2045
 
2099
- /*
2100
- * call-seq:
2101
- * conn.get_result() -> PG::Result
2102
- * conn.get_result() {|pg_result| block }
2103
- *
2104
- * Blocks waiting for the next result from a call to
2105
- * #send_query (or another asynchronous command), and returns
2106
- * it. Returns +nil+ if no more results are available.
2107
- *
2108
- * Note: call this function repeatedly until it returns +nil+, or else
2109
- * you will not be able to issue further commands.
2110
- *
2111
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
2112
- * and the PG::Result object will automatically be cleared when the block terminates.
2113
- * In this instance, <code>conn.exec</code> returns the value of the block.
2114
- */
2115
2046
  static VALUE
2116
- pgconn_get_result(VALUE self)
2047
+ pgconn_sync_get_result(VALUE self)
2117
2048
  {
2118
2049
  PGconn *conn = pg_get_pgconn(self);
2119
2050
  PGresult *result;
@@ -2146,6 +2077,7 @@ pgconn_consume_input(self)
2146
2077
  PGconn *conn = pg_get_pgconn(self);
2147
2078
  /* returns 0 on error */
2148
2079
  if(PQconsumeInput(conn) == 0) {
2080
+ pgconn_close_socket_io(self);
2149
2081
  error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2150
2082
  rb_iv_set(error, "@connection", self);
2151
2083
  rb_exc_raise(error);
@@ -2158,7 +2090,7 @@ pgconn_consume_input(self)
2158
2090
  * conn.is_busy() -> Boolean
2159
2091
  *
2160
2092
  * Returns +true+ if a command is busy, that is, if
2161
- * PQgetResult would block. Otherwise returns +false+.
2093
+ * #get_result would block. Otherwise returns +false+.
2162
2094
  */
2163
2095
  static VALUE
2164
2096
  pgconn_is_busy(self)
@@ -2167,24 +2099,8 @@ pgconn_is_busy(self)
2167
2099
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2168
2100
  }
2169
2101
 
2170
- /*
2171
- * call-seq:
2172
- * conn.setnonblocking(Boolean) -> nil
2173
- *
2174
- * Sets the nonblocking status of the connection.
2175
- * In the blocking state, calls to #send_query
2176
- * will block until the message is sent to the server,
2177
- * but will not wait for the query results.
2178
- * In the nonblocking state, calls to #send_query
2179
- * will return an error if the socket is not ready for
2180
- * writing.
2181
- * Note: This function does not affect #exec, because
2182
- * that function doesn't return until the server has
2183
- * processed the query and returned the results.
2184
- * Returns +nil+.
2185
- */
2186
2102
  static VALUE
2187
- pgconn_setnonblocking(self, state)
2103
+ pgconn_sync_setnonblocking(self, state)
2188
2104
  VALUE self, state;
2189
2105
  {
2190
2106
  int arg;
@@ -2206,33 +2122,15 @@ pgconn_setnonblocking(self, state)
2206
2122
  }
2207
2123
 
2208
2124
 
2209
- /*
2210
- * call-seq:
2211
- * conn.isnonblocking() -> Boolean
2212
- *
2213
- * Returns +true+ if a command is busy, that is, if
2214
- * PQgetResult would block. Otherwise returns +false+.
2215
- */
2216
2125
  static VALUE
2217
- pgconn_isnonblocking(self)
2126
+ pgconn_sync_isnonblocking(self)
2218
2127
  VALUE self;
2219
2128
  {
2220
2129
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2221
2130
  }
2222
2131
 
2223
- /*
2224
- * call-seq:
2225
- * conn.flush() -> Boolean
2226
- *
2227
- * Attempts to flush any queued output data to the server.
2228
- * Returns +true+ if data is successfully flushed, +false+
2229
- * if not (can only return +false+ if connection is
2230
- * nonblocking.
2231
- * Raises PG::Error if some other failure occurred.
2232
- */
2233
2132
  static VALUE
2234
- pgconn_flush(self)
2235
- VALUE self;
2133
+ pgconn_sync_flush(VALUE self)
2236
2134
  {
2237
2135
  PGconn *conn = pg_get_pgconn(self);
2238
2136
  int ret;
@@ -2246,18 +2144,8 @@ pgconn_flush(self)
2246
2144
  return (ret) ? Qfalse : Qtrue;
2247
2145
  }
2248
2146
 
2249
- /*
2250
- * call-seq:
2251
- * conn.cancel() -> String
2252
- *
2253
- * Requests cancellation of the command currently being
2254
- * processed. (Only implemented in PostgreSQL >= 8.0)
2255
- *
2256
- * Returns +nil+ on success, or a string containing the
2257
- * error message if a failure occurs.
2258
- */
2259
2147
  static VALUE
2260
- pgconn_cancel(VALUE self)
2148
+ pgconn_sync_cancel(VALUE self)
2261
2149
  {
2262
2150
  char errbuf[256];
2263
2151
  PGcancel *cancel;
@@ -2268,7 +2156,7 @@ pgconn_cancel(VALUE self)
2268
2156
  if(cancel == NULL)
2269
2157
  rb_raise(rb_ePGerror,"Invalid connection!");
2270
2158
 
2271
- ret = gvl_PQcancel(cancel, errbuf, 256);
2159
+ ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2272
2160
  if(ret == 1)
2273
2161
  retval = Qnil;
2274
2162
  else
@@ -2289,7 +2177,7 @@ pgconn_cancel(VALUE self)
2289
2177
  static VALUE
2290
2178
  pgconn_notifies(VALUE self)
2291
2179
  {
2292
- PGconn* conn = pg_get_pgconn(self);
2180
+ t_pg_connection *this = pg_get_connection_safe( self );
2293
2181
  PGnotify *notification;
2294
2182
  VALUE hash;
2295
2183
  VALUE sym_relname, sym_be_pid, sym_extra;
@@ -2299,17 +2187,17 @@ pgconn_notifies(VALUE self)
2299
2187
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2300
2188
  sym_extra = ID2SYM(rb_intern("extra"));
2301
2189
 
2302
- notification = gvl_PQnotifies(conn);
2190
+ notification = gvl_PQnotifies(this->pgconn);
2303
2191
  if (notification == NULL) {
2304
2192
  return Qnil;
2305
2193
  }
2306
2194
 
2307
2195
  hash = rb_hash_new();
2308
- relname = rb_tainted_str_new2(notification->relname);
2196
+ relname = rb_str_new2(notification->relname);
2309
2197
  be_pid = INT2NUM(notification->be_pid);
2310
- extra = rb_tainted_str_new2(notification->extra);
2311
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2312
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2198
+ extra = rb_str_new2(notification->extra);
2199
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2200
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2313
2201
 
2314
2202
  rb_hash_aset(hash, sym_relname, relname);
2315
2203
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -2319,55 +2207,63 @@ pgconn_notifies(VALUE self)
2319
2207
  return hash;
2320
2208
  }
2321
2209
 
2322
- /* Win32 + Ruby 1.9+ */
2323
- #if defined( _WIN32 )
2324
- /*
2325
- * On Windows, use platform-specific strategies to wait for the socket
2326
- * instead of rb_wait_for_single_fd().
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.
2327
2214
  */
2328
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
+
2329
2226
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2330
2227
 
2331
- static void *
2332
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2333
- {
2334
- int sd = PQsocket( conn );
2335
- void *retval;
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
+
2336
2233
  struct timeval aborttime={0,0}, currtime, waittime;
2337
2234
  DWORD timeout_milisec = INFINITE;
2338
- DWORD wait_ret;
2339
- WSAEVENT hEvent;
2235
+ HANDLE hEvent = WSACreateEvent();
2340
2236
 
2341
- if ( sd < 0 )
2342
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2237
+ long rb_events = NUM2UINT(events);
2238
+ long w32_events = 0;
2239
+ DWORD wait_ret;
2343
2240
 
2344
- hEvent = WSACreateEvent();
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) * 1e6);
2345
2245
 
2346
- /* Check for connection errors (PQisBusy is true on connection errors) */
2347
- if( PQconsumeInput(conn) == 0 ) {
2348
- WSACloseEvent( hEvent );
2349
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2350
- }
2351
-
2352
- if ( ptimeout ) {
2353
2246
  gettimeofday(&currtime, NULL);
2354
- timeradd(&currtime, ptimeout, &aborttime);
2247
+ timeradd(&currtime, &ptimeout, &aborttime);
2355
2248
  }
2356
2249
 
2357
- while ( !(retval=is_readable(conn)) ) {
2358
- if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2250
+ if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2251
+ if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
2252
+ if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
2253
+
2254
+ for(;;) {
2255
+ if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
2359
2256
  WSACloseEvent( hEvent );
2360
2257
  rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2361
2258
  }
2362
2259
 
2363
- if ( ptimeout ) {
2260
+ if ( !NIL_P(timeout) ) {
2364
2261
  gettimeofday(&currtime, NULL);
2365
2262
  timersub(&aborttime, &currtime, &waittime);
2366
2263
  timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
2367
2264
  }
2368
2265
 
2369
- /* Is the given timeout valid? */
2370
- if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2266
+ if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2371
2267
  /* Wait for the socket to become readable before checking again */
2372
2268
  wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2373
2269
  } else {
@@ -2376,9 +2272,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2376
2272
 
2377
2273
  if ( wait_ret == WAIT_TIMEOUT ) {
2378
2274
  WSACloseEvent( hEvent );
2379
- return NULL;
2275
+ return UINT2NUM(0);
2380
2276
  } else if ( wait_ret == WAIT_OBJECT_0 ) {
2277
+ WSACloseEvent( hEvent );
2381
2278
  /* The event we were waiting for. */
2279
+ return UINT2NUM(rb_events);
2382
2280
  } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2383
2281
  /* This indicates interruption from timer thread, GC, exception
2384
2282
  * from other threads etc... */
@@ -2390,36 +2288,75 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2390
2288
  WSACloseEvent( hEvent );
2391
2289
  rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
2392
2290
  }
2393
-
2394
- /* Check for connection errors (PQisBusy is true on connection errors) */
2395
- if ( PQconsumeInput(conn) == 0 ) {
2396
- WSACloseEvent( hEvent );
2397
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2398
- }
2399
2291
  }
2292
+ }
2400
2293
 
2401
- WSACloseEvent( hEvent );
2402
- return retval;
2294
+ static VALUE
2295
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2296
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2297
+ /* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
2298
+ * Fortunatelly ruby-3.1 offers a C-API for it.
2299
+ */
2300
+ VALUE scheduler = rb_fiber_scheduler_current();
2301
+
2302
+ if (!NIL_P(scheduler)) {
2303
+ return rb_io_wait(io, events, timeout);
2304
+ }
2305
+ #endif
2306
+ return pg_rb_thread_io_wait(io, events, timeout);
2403
2307
  }
2404
2308
 
2309
+ #elif defined(HAVE_RB_IO_WAIT)
2310
+
2311
+ /* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
2312
+ #define pg_rb_io_wait rb_io_wait
2313
+ #define PG_RUBY_IO_READABLE RUBY_IO_READABLE
2314
+ #define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
2315
+ #define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
2316
+
2405
2317
  #else
2318
+ /* For compat with ruby < 3.0 */
2319
+
2320
+ typedef enum {
2321
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2322
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2323
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2324
+ } pg_rb_io_event_t;
2325
+
2326
+ static VALUE
2327
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2328
+ rb_io_t *fptr;
2329
+ struct timeval waittime;
2330
+ int res;
2331
+
2332
+ GetOpenFile((io), fptr);
2333
+ if( !NIL_P(timeout) ){
2334
+ waittime.tv_sec = (time_t)(NUM2DBL(timeout));
2335
+ waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
2336
+ }
2337
+ res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
2406
2338
 
2407
- /* non Win32 */
2339
+ return UINT2NUM(res);
2340
+ }
2341
+ #endif
2408
2342
 
2409
2343
  static void *
2410
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2344
+ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2411
2345
  {
2412
- int sd = PQsocket( conn );
2413
- int ret;
2346
+ VALUE socket_io;
2347
+ VALUE ret;
2414
2348
  void *retval;
2415
2349
  struct timeval aborttime={0,0}, currtime, waittime;
2350
+ VALUE wait_timeout = Qnil;
2351
+ PGconn *conn = pg_get_pgconn(self);
2416
2352
 
2417
- if ( sd < 0 )
2418
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2353
+ socket_io = pgconn_socket_io(self);
2419
2354
 
2420
2355
  /* Check for connection errors (PQisBusy is true on connection errors) */
2421
- if ( PQconsumeInput(conn) == 0 )
2356
+ if ( PQconsumeInput(conn) == 0 ) {
2357
+ pgconn_close_socket_io(self);
2422
2358
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2359
+ }
2423
2360
 
2424
2361
  if ( ptimeout ) {
2425
2362
  gettimeofday(&currtime, NULL);
@@ -2430,27 +2367,25 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2430
2367
  if ( ptimeout ) {
2431
2368
  gettimeofday(&currtime, NULL);
2432
2369
  timersub(&aborttime, &currtime, &waittime);
2370
+ wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
2433
2371
  }
2434
2372
 
2435
2373
  /* Is the given timeout valid? */
2436
2374
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2437
2375
  /* Wait for the socket to become readable before checking again */
2438
- ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
2376
+ ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2439
2377
  } else {
2440
- ret = 0;
2441
- }
2442
-
2443
- if ( ret < 0 ){
2444
- rb_sys_fail( "rb_wait_for_single_fd()" );
2378
+ ret = Qfalse;
2445
2379
  }
2446
2380
 
2447
2381
  /* Return false if the select() timed out */
2448
- if ( ret == 0 ){
2382
+ if ( ret == Qfalse ){
2449
2383
  return NULL;
2450
2384
  }
2451
2385
 
2452
2386
  /* Check for connection errors (PQisBusy is true on connection errors) */
2453
2387
  if ( PQconsumeInput(conn) == 0 ){
2388
+ pgconn_close_socket_io(self);
2454
2389
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2455
2390
  }
2456
2391
  }
@@ -2458,8 +2393,45 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2458
2393
  return retval;
2459
2394
  }
2460
2395
 
2396
+ /*
2397
+ * call-seq:
2398
+ * conn.flush() -> Boolean
2399
+ *
2400
+ * Attempts to flush any queued output data to the server.
2401
+ * Returns +true+ if data is successfully flushed, +false+
2402
+ * if not (can only return +false+ if connection is
2403
+ * nonblocking.
2404
+ * Raises PG::Error if some other failure occurred.
2405
+ */
2406
+ static VALUE
2407
+ pgconn_async_flush(VALUE self)
2408
+ {
2409
+ while( pgconn_sync_flush(self) == Qfalse ){
2410
+ /* wait for the socket to become read- or write-ready */
2411
+ int events;
2412
+ VALUE socket_io = pgconn_socket_io(self);
2413
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2414
+
2415
+ if (events & PG_RUBY_IO_READABLE)
2416
+ pgconn_consume_input(self);
2417
+ }
2418
+ return Qtrue;
2419
+ }
2420
+
2421
+ static VALUE
2422
+ pgconn_wait_for_flush( VALUE self ){
2423
+ if( !pg_get_connection_safe(self)->flush_data )
2424
+ return Qnil;
2461
2425
 
2462
- #endif
2426
+ return pgconn_async_flush(self);
2427
+ }
2428
+
2429
+ static VALUE
2430
+ pgconn_flush_data_set( VALUE self, VALUE enabled ){
2431
+ t_pg_connection *conn = pg_get_connection(self);
2432
+ conn->flush_data = RTEST(enabled);
2433
+ return enabled;
2434
+ }
2463
2435
 
2464
2436
  static void *
2465
2437
  notify_readable(PGconn *conn)
@@ -2482,7 +2454,7 @@ notify_readable(PGconn *conn)
2482
2454
  static VALUE
2483
2455
  pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2484
2456
  {
2485
- PGconn *conn = pg_get_pgconn( self );
2457
+ t_pg_connection *this = pg_get_connection_safe( self );
2486
2458
  PGnotify *pnotification;
2487
2459
  struct timeval timeout;
2488
2460
  struct timeval *ptimeout = NULL;
@@ -2498,17 +2470,17 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2498
2470
  ptimeout = &timeout;
2499
2471
  }
2500
2472
 
2501
- pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
2473
+ pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
2502
2474
 
2503
2475
  /* Return nil if the select timed out */
2504
2476
  if ( !pnotification ) return Qnil;
2505
2477
 
2506
- relname = rb_tainted_str_new2( pnotification->relname );
2507
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2478
+ relname = rb_str_new2( pnotification->relname );
2479
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2508
2480
  be_pid = INT2NUM( pnotification->be_pid );
2509
2481
  if ( *pnotification->extra ) {
2510
- extra = rb_tainted_str_new2( pnotification->extra );
2511
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2482
+ extra = rb_str_new2( pnotification->extra );
2483
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2512
2484
  }
2513
2485
  PQfreemem( pnotification );
2514
2486
 
@@ -2519,28 +2491,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2519
2491
  }
2520
2492
 
2521
2493
 
2522
- /*
2523
- * call-seq:
2524
- * conn.put_copy_data( buffer [, encoder] ) -> Boolean
2525
- *
2526
- * Transmits _buffer_ as copy data to the server.
2527
- * Returns true if the data was sent, false if it was
2528
- * not sent (false is only possible if the connection
2529
- * is in nonblocking mode, and this command would block).
2530
- *
2531
- * _encoder_ can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
2532
- * This encodes the data fields given as _buffer_ from an Array of Strings to
2533
- * PostgreSQL's COPY text format inclusive proper escaping. Optionally
2534
- * the encoder can type cast the fields from various Ruby types in one step,
2535
- * if PG::TextEncoder::CopyRow#type_map is set accordingly.
2536
- *
2537
- * Raises an exception if an error occurs.
2538
- *
2539
- * See also #copy_data.
2540
- *
2541
- */
2542
2494
  static VALUE
2543
- pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2495
+ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2544
2496
  {
2545
2497
  int ret;
2546
2498
  int len;
@@ -2557,18 +2509,16 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2557
2509
  if( NIL_P(this->encoder_for_put_copy_data) ){
2558
2510
  buffer = value;
2559
2511
  } else {
2560
- p_coder = DATA_PTR( this->encoder_for_put_copy_data );
2512
+ p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
2561
2513
  }
2562
- } else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
2563
- Data_Get_Struct( encoder, t_pg_coder, p_coder );
2564
2514
  } else {
2565
- rb_raise( rb_eTypeError, "wrong encoder type %s (expected some kind of PG::Coder)",
2566
- rb_obj_classname( encoder ) );
2515
+ /* Check argument type and use argument encoder */
2516
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
2567
2517
  }
2568
2518
 
2569
2519
  if( p_coder ){
2570
2520
  t_pg_coder_enc_func enc_func;
2571
- int enc_idx = ENCODING_GET(self);
2521
+ int enc_idx = this->enc_idx;
2572
2522
 
2573
2523
  enc_func = pg_coder_enc_func( p_coder );
2574
2524
  len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
@@ -2597,64 +2547,31 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2597
2547
  return (ret) ? Qtrue : Qfalse;
2598
2548
  }
2599
2549
 
2600
- /*
2601
- * call-seq:
2602
- * conn.put_copy_end( [ error_message ] ) -> Boolean
2603
- *
2604
- * Sends end-of-data indication to the server.
2605
- *
2606
- * _error_message_ is an optional parameter, and if set,
2607
- * forces the COPY command to fail with the string
2608
- * _error_message_.
2609
- *
2610
- * Returns true if the end-of-data was sent, false if it was
2611
- * not sent (false is only possible if the connection
2612
- * is in nonblocking mode, and this command would block).
2613
- */
2614
2550
  static VALUE
2615
- pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2551
+ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2616
2552
  {
2617
2553
  VALUE str;
2618
2554
  VALUE error;
2619
2555
  int ret;
2620
2556
  const char *error_message = NULL;
2621
- PGconn *conn = pg_get_pgconn(self);
2557
+ t_pg_connection *this = pg_get_connection_safe( self );
2622
2558
 
2623
2559
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2624
2560
  error_message = NULL;
2625
2561
  else
2626
- error_message = pg_cstr_enc(str, ENCODING_GET(self));
2562
+ error_message = pg_cstr_enc(str, this->enc_idx);
2627
2563
 
2628
- ret = gvl_PQputCopyEnd(conn, error_message);
2564
+ ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2629
2565
  if(ret == -1) {
2630
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2566
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2631
2567
  rb_iv_set(error, "@connection", self);
2632
2568
  rb_exc_raise(error);
2633
2569
  }
2634
2570
  return (ret) ? Qtrue : Qfalse;
2635
2571
  }
2636
2572
 
2637
- /*
2638
- * call-seq:
2639
- * conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> Object
2640
- *
2641
- * Return one row of data, +nil+
2642
- * if the copy is done, or +false+ if the call would
2643
- * block (only possible if _async_ is true).
2644
- *
2645
- * If _decoder_ is not set or +nil+, data is returned as binary string.
2646
- *
2647
- * If _decoder_ is set to a PG::Coder derivation, the return type depends on this decoder.
2648
- * PG::TextDecoder::CopyRow decodes the received data fields from one row of PostgreSQL's
2649
- * COPY text format to an Array of Strings.
2650
- * Optionally the decoder can type cast the single fields to various Ruby types in one step,
2651
- * if PG::TextDecoder::CopyRow#type_map is set accordingly.
2652
- *
2653
- * See also #copy_data.
2654
- *
2655
- */
2656
2573
  static VALUE
2657
- pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2574
+ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2658
2575
  {
2659
2576
  VALUE async_in;
2660
2577
  VALUE error;
@@ -2669,13 +2586,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2669
2586
 
2670
2587
  if( NIL_P(decoder) ){
2671
2588
  if( !NIL_P(this->decoder_for_get_copy_data) ){
2672
- p_coder = DATA_PTR( this->decoder_for_get_copy_data );
2589
+ p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
2673
2590
  }
2674
- } else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
2675
- Data_Get_Struct( decoder, t_pg_coder, p_coder );
2676
2591
  } else {
2677
- rb_raise( rb_eTypeError, "wrong decoder type %s (expected some kind of PG::Coder)",
2678
- rb_obj_classname( decoder ) );
2592
+ /* Check argument type and use argument decoder */
2593
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
2679
2594
  }
2680
2595
 
2681
2596
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
@@ -2693,9 +2608,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2693
2608
 
2694
2609
  if( p_coder ){
2695
2610
  t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
2696
- result = dec_func( p_coder, buffer, ret, 0, 0, ENCODING_GET(self) );
2611
+ result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2697
2612
  } else {
2698
- result = rb_tainted_str_new(buffer, ret);
2613
+ result = rb_str_new(buffer, ret);
2699
2614
  }
2700
2615
 
2701
2616
  PQfreemem(buffer);
@@ -2708,9 +2623,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2708
2623
  *
2709
2624
  * Sets connection's verbosity to _verbosity_ and returns
2710
2625
  * the previous setting. Available settings are:
2626
+ *
2711
2627
  * * PQERRORS_TERSE
2712
2628
  * * PQERRORS_DEFAULT
2713
2629
  * * PQERRORS_VERBOSE
2630
+ * * PQERRORS_SQLSTATE
2631
+ *
2632
+ * Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2633
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
2634
+ *
2635
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
2714
2636
  */
2715
2637
  static VALUE
2716
2638
  pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
@@ -2720,6 +2642,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2720
2642
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2721
2643
  }
2722
2644
 
2645
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2646
+ /*
2647
+ * call-seq:
2648
+ * conn.set_error_context_visibility( context_visibility ) -> Integer
2649
+ *
2650
+ * Sets connection's context display mode to _context_visibility_ and returns
2651
+ * the previous setting. Available settings are:
2652
+ * * PQSHOW_CONTEXT_NEVER
2653
+ * * PQSHOW_CONTEXT_ERRORS
2654
+ * * PQSHOW_CONTEXT_ALWAYS
2655
+ *
2656
+ * This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
2657
+ * The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
2658
+ * In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
2659
+ *
2660
+ * Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2661
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
2662
+ *
2663
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2664
+ *
2665
+ * Available since PostgreSQL-9.6
2666
+ */
2667
+ static VALUE
2668
+ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2669
+ {
2670
+ PGconn *conn = pg_get_pgconn(self);
2671
+ PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2672
+ return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2673
+ }
2674
+ #endif
2675
+
2723
2676
  /*
2724
2677
  * call-seq:
2725
2678
  * conn.trace( stream ) -> nil
@@ -2738,7 +2691,7 @@ pgconn_trace(VALUE self, VALUE stream)
2738
2691
  VALUE new_file;
2739
2692
  t_pg_connection *this = pg_get_connection_safe( self );
2740
2693
 
2741
- if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2694
+ if(!rb_respond_to(stream,rb_intern("fileno")))
2742
2695
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2743
2696
 
2744
2697
  fileno = rb_funcall(stream, rb_intern("fileno"), 0);
@@ -2871,8 +2824,8 @@ notice_processor_proxy(void *arg, const char *message)
2871
2824
  t_pg_connection *this = pg_get_connection( self );
2872
2825
 
2873
2826
  if (this->notice_receiver != Qnil) {
2874
- VALUE message_str = rb_tainted_str_new2(message);
2875
- PG_ENCODING_SET_NOCHECK( message_str, ENCODING_GET(self) );
2827
+ VALUE message_str = rb_str_new2(message);
2828
+ PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2876
2829
  rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2877
2830
  }
2878
2831
  return;
@@ -2882,7 +2835,7 @@ notice_processor_proxy(void *arg, const char *message)
2882
2835
  * call-seq:
2883
2836
  * conn.set_notice_processor {|message| ... } -> Proc
2884
2837
  *
2885
- * See #set_notice_receiver for the desription of what this and the
2838
+ * See #set_notice_receiver for the description of what this and the
2886
2839
  * notice_processor methods do.
2887
2840
  *
2888
2841
  * This function takes a new block to act as the notice processor and returns
@@ -2930,18 +2883,20 @@ static VALUE
2930
2883
  pgconn_get_client_encoding(VALUE self)
2931
2884
  {
2932
2885
  char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2933
- return rb_tainted_str_new2(encoding);
2886
+ return rb_str_new2(encoding);
2934
2887
  }
2935
2888
 
2936
2889
 
2937
2890
  /*
2938
2891
  * call-seq:
2939
- * conn.set_client_encoding( encoding )
2892
+ * conn.sync_set_client_encoding( encoding )
2940
2893
  *
2941
- * Sets the client encoding to the _encoding_ String.
2894
+ * This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
2895
+ * See #async_exec for the differences between the two API variants.
2896
+ * 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.
2942
2897
  */
2943
2898
  static VALUE
2944
- pgconn_set_client_encoding(VALUE self, VALUE str)
2899
+ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2945
2900
  {
2946
2901
  PGconn *conn = pg_get_pgconn( self );
2947
2902
 
@@ -2955,49 +2910,6 @@ pgconn_set_client_encoding(VALUE self, VALUE str)
2955
2910
  return Qnil;
2956
2911
  }
2957
2912
 
2958
- /*
2959
- * call-seq:
2960
- * conn.transaction { |conn| ... } -> result of the block
2961
- *
2962
- * Executes a +BEGIN+ at the start of the block,
2963
- * and a +COMMIT+ at the end of the block, or
2964
- * +ROLLBACK+ if any exception occurs.
2965
- */
2966
- static VALUE
2967
- pgconn_transaction(VALUE self)
2968
- {
2969
- PGconn *conn = pg_get_pgconn(self);
2970
- PGresult *result;
2971
- VALUE rb_pgresult;
2972
- VALUE block_result = Qnil;
2973
- int status;
2974
-
2975
- if (rb_block_given_p()) {
2976
- result = gvl_PQexec(conn, "BEGIN");
2977
- rb_pgresult = pg_new_result(result, self);
2978
- pg_result_check(rb_pgresult);
2979
- block_result = rb_protect(rb_yield, self, &status);
2980
- if(status == 0) {
2981
- result = gvl_PQexec(conn, "COMMIT");
2982
- rb_pgresult = pg_new_result(result, self);
2983
- pg_result_check(rb_pgresult);
2984
- }
2985
- else {
2986
- /* exception occurred, ROLLBACK and re-raise */
2987
- result = gvl_PQexec(conn, "ROLLBACK");
2988
- rb_pgresult = pg_new_result(result, self);
2989
- pg_result_check(rb_pgresult);
2990
- rb_jump_tag(status);
2991
- }
2992
-
2993
- }
2994
- else {
2995
- /* no block supplied? */
2996
- rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
2997
- }
2998
- return block_result;
2999
- }
3000
-
3001
2913
 
3002
2914
  /*
3003
2915
  * call-seq:
@@ -3042,14 +2954,12 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3042
2954
  int enc_idx;
3043
2955
 
3044
2956
  if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3045
- enc_idx = ENCODING_GET( self );
2957
+ enc_idx = pg_get_connection(self)->enc_idx;
3046
2958
  }else{
3047
2959
  enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3048
2960
  }
3049
2961
  pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3050
2962
 
3051
- OBJ_INFECT(ret, str_or_array);
3052
-
3053
2963
  return ret;
3054
2964
  }
3055
2965
 
@@ -3076,8 +2986,6 @@ get_result_readable(PGconn *conn)
3076
2986
  */
3077
2987
  static VALUE
3078
2988
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
3079
- PGconn *conn = pg_get_pgconn( self );
3080
-
3081
2989
  struct timeval timeout;
3082
2990
  struct timeval *ptimeout = NULL;
3083
2991
  VALUE timeout_in;
@@ -3091,7 +2999,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3091
2999
  ptimeout = &timeout;
3092
3000
  }
3093
3001
 
3094
- ret = wait_socket_readable( conn, ptimeout, get_result_readable);
3002
+ ret = wait_socket_readable( self, ptimeout, get_result_readable);
3095
3003
 
3096
3004
  if( !ret )
3097
3005
  return Qfalse;
@@ -3100,6 +3008,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3100
3008
  }
3101
3009
 
3102
3010
 
3011
+ /*
3012
+ * call-seq:
3013
+ * conn.sync_get_last_result( ) -> PG::Result
3014
+ *
3015
+ * This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
3016
+ * See #async_exec for the differences between the two API variants.
3017
+ * 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.
3018
+ */
3019
+ static VALUE
3020
+ pgconn_sync_get_last_result(VALUE self)
3021
+ {
3022
+ PGconn *conn = pg_get_pgconn(self);
3023
+ VALUE rb_pgresult = Qnil;
3024
+ PGresult *cur, *prev;
3025
+
3026
+
3027
+ cur = prev = NULL;
3028
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
3029
+ int status;
3030
+
3031
+ if (prev) PQclear(prev);
3032
+ prev = cur;
3033
+
3034
+ status = PQresultStatus(cur);
3035
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3036
+ break;
3037
+ }
3038
+
3039
+ if (prev) {
3040
+ rb_pgresult = pg_new_result( prev, self );
3041
+ pg_result_check(rb_pgresult);
3042
+ }
3043
+
3044
+ return rb_pgresult;
3045
+ }
3046
+
3103
3047
  /*
3104
3048
  * call-seq:
3105
3049
  * conn.get_last_result( ) -> PG::Result
@@ -3110,27 +3054,35 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3110
3054
  * returns the last non-NULL result, or +nil+ if no
3111
3055
  * results are available.
3112
3056
  *
3057
+ * If the last result contains a bad result_status, an
3058
+ * appropriate exception is raised.
3059
+ *
3113
3060
  * This function is similar to #get_result
3114
3061
  * except that it is designed to get one and only
3115
- * one result.
3062
+ * one result and that it checks the result state.
3116
3063
  */
3117
3064
  static VALUE
3118
- pgconn_get_last_result(VALUE self)
3065
+ pgconn_async_get_last_result(VALUE self)
3119
3066
  {
3120
3067
  PGconn *conn = pg_get_pgconn(self);
3121
3068
  VALUE rb_pgresult = Qnil;
3122
3069
  PGresult *cur, *prev;
3123
3070
 
3124
-
3125
- cur = prev = NULL;
3126
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3071
+ cur = prev = NULL;
3072
+ for(;;) {
3127
3073
  int status;
3128
3074
 
3075
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3076
+
3077
+ cur = gvl_PQgetResult(conn);
3078
+ if (cur == NULL)
3079
+ break;
3080
+
3129
3081
  if (prev) PQclear(prev);
3130
3082
  prev = cur;
3131
3083
 
3132
3084
  status = PQresultStatus(cur);
3133
- if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
3085
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3134
3086
  break;
3135
3087
  }
3136
3088
 
@@ -3154,39 +3106,89 @@ static VALUE
3154
3106
  pgconn_discard_results(VALUE self)
3155
3107
  {
3156
3108
  PGconn *conn = pg_get_pgconn(self);
3109
+ VALUE socket_io;
3157
3110
 
3158
- PGresult *cur;
3159
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3160
- int status = PQresultStatus(cur);
3111
+ if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3112
+ return Qnil;
3113
+ }
3114
+
3115
+ socket_io = pgconn_socket_io(self);
3116
+
3117
+ for(;;) {
3118
+ PGresult *cur;
3119
+ int status;
3120
+
3121
+ /* pgconn_block() raises an exception in case of errors.
3122
+ * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3123
+ */
3124
+ while( gvl_PQisBusy(conn) ){
3125
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3126
+ if ( PQconsumeInput(conn) == 0 ) {
3127
+ pgconn_close_socket_io(self);
3128
+ return Qfalse;
3129
+ }
3130
+ }
3131
+
3132
+ cur = gvl_PQgetResult(conn);
3133
+ if( cur == NULL) break;
3134
+
3135
+ status = PQresultStatus(cur);
3161
3136
  PQclear(cur);
3162
3137
  if (status == PGRES_COPY_IN){
3163
3138
  gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
3164
3139
  }
3165
3140
  if (status == PGRES_COPY_OUT){
3166
- char *buffer = NULL;
3167
- while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
3168
- PQfreemem(buffer);
3141
+ for(;;) {
3142
+ char *buffer = NULL;
3143
+ int st = gvl_PQgetCopyData(conn, &buffer, 1);
3144
+ if( st == 0 ) {
3145
+ /* would block -> wait for readable data */
3146
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3147
+ if ( PQconsumeInput(conn) == 0 ) {
3148
+ pgconn_close_socket_io(self);
3149
+ return Qfalse;
3150
+ }
3151
+ } else if( st > 0 ) {
3152
+ /* some data retrieved -> discard it */
3153
+ PQfreemem(buffer);
3154
+ } else {
3155
+ /* no more data */
3156
+ break;
3157
+ }
3158
+ }
3169
3159
  }
3170
3160
  }
3171
3161
 
3172
- return Qnil;
3162
+ return Qtrue;
3173
3163
  }
3174
3164
 
3175
3165
  /*
3176
3166
  * call-seq:
3177
- * conn.async_exec(sql) -> PG::Result
3178
- * conn.async_exec(sql) {|pg_result| block }
3167
+ * conn.exec(sql) -> PG::Result
3168
+ * conn.exec(sql) {|pg_result| block }
3179
3169
  *
3180
- * This function has the same behavior as #sync_exec,
3181
- * but is implemented using the asynchronous command
3182
- * processing API of libpq.
3170
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
3171
+ * On success, it returns a PG::Result instance with all result rows and columns.
3172
+ * On failure, it raises a PG::Error.
3183
3173
  *
3184
- * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
3185
- * However #async_exec has two advantages:
3174
+ * For backward compatibility, if you pass more than one parameter to this method,
3175
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
3176
+ * argument placeholders are used.
3186
3177
  *
3187
- * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
3188
- * 2. Ruby VM gets notified about IO blocked operations.
3189
- * It can therefore schedule thing like garbage collection, while queries are running like in this proposal: https://bugs.ruby-lang.org/issues/14723
3178
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3179
+ * and the PG::Result object will automatically be cleared when the block terminates.
3180
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3181
+ *
3182
+ * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3183
+ * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3184
+ * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3185
+ * Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
3186
+ * Both methods ensure that other threads can process while waiting for the server to
3187
+ * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3188
+ * This is most notably visible by a delayed reaction to Control+C.
3189
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3190
+ *
3191
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
3190
3192
  */
3191
3193
  static VALUE
3192
3194
  pgconn_async_exec(int argc, VALUE *argv, VALUE self)
@@ -3195,8 +3197,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3195
3197
 
3196
3198
  pgconn_discard_results( self );
3197
3199
  pgconn_send_query( argc, argv, self );
3198
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3199
- rb_pgresult = pgconn_get_last_result( self );
3200
+ rb_pgresult = pgconn_async_get_last_result( self );
3200
3201
 
3201
3202
  if ( rb_block_given_p() ) {
3202
3203
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3207,11 +3208,53 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3207
3208
 
3208
3209
  /*
3209
3210
  * call-seq:
3210
- * conn.async_exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3211
- * conn.async_exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3211
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3212
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3212
3213
  *
3213
- * This function has the same behavior as #sync_exec_params, but is implemented using the asynchronous command processing API of libpq.
3214
- * See #async_exec for the differences between the two API variants.
3214
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
3215
+ * for parameters.
3216
+ *
3217
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
3218
+ *
3219
+ * +params+ is an array of the bind parameters for the SQL query.
3220
+ * Each element of the +params+ array may be either:
3221
+ * a hash of the form:
3222
+ * {:value => String (value of bind parameter)
3223
+ * :type => Integer (oid of type of bind parameter)
3224
+ * :format => Integer (0 for text, 1 for binary)
3225
+ * }
3226
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3227
+ * { :value => <string value>, :type => 0, :format => 0 }
3228
+ *
3229
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3230
+ * inside the SQL query. The 0th element of the +params+ array is bound
3231
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3232
+ *
3233
+ * If the types are not specified, they will be inferred by PostgreSQL.
3234
+ * Instead of specifying type oids, it's recommended to simply add
3235
+ * explicit casts in the query to ensure that the right type is used.
3236
+ *
3237
+ * For example: "SELECT $1::int"
3238
+ *
3239
+ * The optional +result_format+ should be 0 for text results, 1
3240
+ * for binary.
3241
+ *
3242
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3243
+ * This will type cast the params from various Ruby types before transmission
3244
+ * based on the encoders defined by the type map. When a type encoder is used
3245
+ * the format and oid of a given bind parameter are retrieved from the encoder
3246
+ * instead out of the hash form described above.
3247
+ *
3248
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3249
+ * and the PG::Result object will automatically be cleared when the block terminates.
3250
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3251
+ *
3252
+ * The primary advantage of #exec_params over #exec is that parameter values can be separated from the command string, thus avoiding the need for tedious and error-prone quoting and escaping.
3253
+ * Unlike #exec, #exec_params allows at most one SQL command in the given string.
3254
+ * (There can be semicolons in it, but not more than one nonempty command.)
3255
+ * This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
3256
+ *
3257
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
3215
3258
  */
3216
3259
  static VALUE
3217
3260
  pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
@@ -3226,8 +3269,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3226
3269
  } else {
3227
3270
  pgconn_send_query_params( argc, argv, self );
3228
3271
  }
3229
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3230
- rb_pgresult = pgconn_get_last_result( self );
3272
+ rb_pgresult = pgconn_async_get_last_result( self );
3231
3273
 
3232
3274
  if ( rb_block_given_p() ) {
3233
3275
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3238,10 +3280,25 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3238
3280
 
3239
3281
  /*
3240
3282
  * call-seq:
3241
- * conn.async_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3283
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3242
3284
  *
3243
- * This function has the same behavior as #sync_prepare, but is implemented using the asynchronous command processing API of libpq.
3244
- * See #async_exec for the differences between the two API variants.
3285
+ * Prepares statement _sql_ with name _name_ to be executed later.
3286
+ * Returns a PG::Result instance on success.
3287
+ * On failure, it raises a PG::Error.
3288
+ *
3289
+ * +param_types+ is an optional parameter to specify the Oids of the
3290
+ * types of the parameters.
3291
+ *
3292
+ * If the types are not specified, they will be inferred by PostgreSQL.
3293
+ * Instead of specifying type oids, it's recommended to simply add
3294
+ * explicit casts in the query to ensure that the right type is used.
3295
+ *
3296
+ * For example: "SELECT $1::int"
3297
+ *
3298
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3299
+ * inside the SQL query.
3300
+ *
3301
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
3245
3302
  */
3246
3303
  static VALUE
3247
3304
  pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
@@ -3250,8 +3307,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3250
3307
 
3251
3308
  pgconn_discard_results( self );
3252
3309
  pgconn_send_prepare( argc, argv, self );
3253
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3254
- rb_pgresult = pgconn_get_last_result( self );
3310
+ rb_pgresult = pgconn_async_get_last_result( self );
3255
3311
 
3256
3312
  if ( rb_block_given_p() ) {
3257
3313
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3262,11 +3318,40 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3262
3318
 
3263
3319
  /*
3264
3320
  * call-seq:
3265
- * conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3266
- * conn.async_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3321
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3322
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3267
3323
  *
3268
- * This function has the same behavior as #sync_exec_prepared, but is implemented using the asynchronous command processing API of libpq.
3269
- * See #async_exec for the differences between the two API variants.
3324
+ * Execute prepared named statement specified by _statement_name_.
3325
+ * Returns a PG::Result instance on success.
3326
+ * On failure, it raises a PG::Error.
3327
+ *
3328
+ * +params+ is an array of the optional bind parameters for the
3329
+ * SQL query. Each element of the +params+ array may be either:
3330
+ * a hash of the form:
3331
+ * {:value => String (value of bind parameter)
3332
+ * :format => Integer (0 for text, 1 for binary)
3333
+ * }
3334
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3335
+ * { :value => <string value>, :format => 0 }
3336
+ *
3337
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3338
+ * inside the SQL query. The 0th element of the +params+ array is bound
3339
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3340
+ *
3341
+ * The optional +result_format+ should be 0 for text results, 1
3342
+ * for binary.
3343
+ *
3344
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3345
+ * This will type cast the params from various Ruby types before transmission
3346
+ * based on the encoders defined by the type map. When a type encoder is used
3347
+ * the format and oid of a given bind parameter are retrieved from the encoder
3348
+ * instead out of the hash form described above.
3349
+ *
3350
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3351
+ * and the PG::Result object will automatically be cleared when the block terminates.
3352
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
3353
+ *
3354
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
3270
3355
  */
3271
3356
  static VALUE
3272
3357
  pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
@@ -3275,8 +3360,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3275
3360
 
3276
3361
  pgconn_discard_results( self );
3277
3362
  pgconn_send_query_prepared( argc, argv, self );
3278
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3279
- rb_pgresult = pgconn_get_last_result( self );
3363
+ rb_pgresult = pgconn_async_get_last_result( self );
3280
3364
 
3281
3365
  if ( rb_block_given_p() ) {
3282
3366
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3287,10 +3371,11 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3287
3371
 
3288
3372
  /*
3289
3373
  * call-seq:
3290
- * conn.async_describe_portal( portal_name ) -> PG::Result
3374
+ * conn.describe_portal( portal_name ) -> PG::Result
3291
3375
  *
3292
- * This function has the same behavior as #sync_describe_portal, but is implemented using the asynchronous command processing API of libpq.
3293
- * See #async_exec for the differences between the two API variants.
3376
+ * Retrieve information about the portal _portal_name_.
3377
+ *
3378
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
3294
3379
  */
3295
3380
  static VALUE
3296
3381
  pgconn_async_describe_portal(VALUE self, VALUE portal)
@@ -3299,8 +3384,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3299
3384
 
3300
3385
  pgconn_discard_results( self );
3301
3386
  pgconn_send_describe_portal( self, portal );
3302
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3303
- rb_pgresult = pgconn_get_last_result( self );
3387
+ rb_pgresult = pgconn_async_get_last_result( self );
3304
3388
 
3305
3389
  if ( rb_block_given_p() ) {
3306
3390
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3311,10 +3395,11 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3311
3395
 
3312
3396
  /*
3313
3397
  * call-seq:
3314
- * conn.async_describe_prepared( statement_name ) -> PG::Result
3398
+ * conn.describe_prepared( statement_name ) -> PG::Result
3315
3399
  *
3316
- * This function has the same behavior as #sync_describe_prepared, but is implemented using the asynchronous command processing API of libpq.
3317
- * See #async_exec for the differences between the two API variants.
3400
+ * Retrieve information about the prepared statement _statement_name_.
3401
+ *
3402
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
3318
3403
  */
3319
3404
  static VALUE
3320
3405
  pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
@@ -3323,8 +3408,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3323
3408
 
3324
3409
  pgconn_discard_results( self );
3325
3410
  pgconn_send_describe_prepared( self, stmt_name );
3326
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3327
- rb_pgresult = pgconn_get_last_result( self );
3411
+ rb_pgresult = pgconn_async_get_last_result( self );
3328
3412
 
3329
3413
  if ( rb_block_given_p() ) {
3330
3414
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3338,7 +3422,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3338
3422
  * call-seq:
3339
3423
  * conn.ssl_in_use? -> Boolean
3340
3424
  *
3341
- * Returns +true+ if the connection uses SSL, +false+ if not.
3425
+ * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3342
3426
  *
3343
3427
  * Available since PostgreSQL-9.5
3344
3428
  */
@@ -3372,7 +3456,7 @@ pgconn_ssl_in_use(VALUE self)
3372
3456
  * If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
3373
3457
  *
3374
3458
  *
3375
- * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3459
+ * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3376
3460
  *
3377
3461
  * Available since PostgreSQL-9.5
3378
3462
  */
@@ -3412,6 +3496,126 @@ pgconn_ssl_attribute_names(VALUE self)
3412
3496
  #endif
3413
3497
 
3414
3498
 
3499
+ #ifdef HAVE_PQENTERPIPELINEMODE
3500
+ /*
3501
+ * call-seq:
3502
+ * conn.pipeline_status -> Integer
3503
+ *
3504
+ * Returns the current pipeline mode status of the libpq connection.
3505
+ *
3506
+ * PQpipelineStatus can return one of the following values:
3507
+ *
3508
+ * * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
3509
+ * * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
3510
+ * * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
3511
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
3512
+ *
3513
+ * Available since PostgreSQL-14
3514
+ */
3515
+ static VALUE
3516
+ pgconn_pipeline_status(VALUE self)
3517
+ {
3518
+ int res = PQpipelineStatus(pg_get_pgconn(self));
3519
+ return INT2FIX(res);
3520
+ }
3521
+
3522
+
3523
+ /*
3524
+ * call-seq:
3525
+ * conn.enter_pipeline_mode -> nil
3526
+ *
3527
+ * Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
3528
+ *
3529
+ * 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.
3530
+ * This function does not actually send anything to the server, it just changes the libpq connection state.
3531
+ *
3532
+ * Available since PostgreSQL-14
3533
+ */
3534
+ static VALUE
3535
+ pgconn_enter_pipeline_mode(VALUE self)
3536
+ {
3537
+ PGconn *conn = pg_get_pgconn(self);
3538
+ int res = PQenterPipelineMode(conn);
3539
+ if( res == 1 ) {
3540
+ return Qnil;
3541
+ } else {
3542
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3543
+ }
3544
+ }
3545
+
3546
+ /*
3547
+ * call-seq:
3548
+ * conn.exit_pipeline_mode -> nil
3549
+ *
3550
+ * Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
3551
+ *
3552
+ * Takes no action if not in pipeline mode.
3553
+ * 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.
3554
+ *
3555
+ * Available since PostgreSQL-14
3556
+ */
3557
+ static VALUE
3558
+ pgconn_exit_pipeline_mode(VALUE self)
3559
+ {
3560
+ PGconn *conn = pg_get_pgconn(self);
3561
+ int res = PQexitPipelineMode(conn);
3562
+ if( res == 1 ) {
3563
+ return Qnil;
3564
+ } else {
3565
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3566
+ }
3567
+ }
3568
+
3569
+
3570
+ /*
3571
+ * call-seq:
3572
+ * conn.pipeline_sync -> nil
3573
+ *
3574
+ * Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
3575
+ * This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
3576
+ *
3577
+ * Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
3578
+ *
3579
+ * Available since PostgreSQL-14
3580
+ */
3581
+ static VALUE
3582
+ pgconn_pipeline_sync(VALUE self)
3583
+ {
3584
+ PGconn *conn = pg_get_pgconn(self);
3585
+ int res = PQpipelineSync(conn);
3586
+ if( res == 1 ) {
3587
+ return Qnil;
3588
+ } else {
3589
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3590
+ }
3591
+ }
3592
+
3593
+ /*
3594
+ * call-seq:
3595
+ * conn.pipeline_sync -> nil
3596
+ *
3597
+ * Sends a request for the server to flush its output buffer.
3598
+ *
3599
+ * 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.
3600
+ * This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
3601
+ * Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
3602
+ *
3603
+ * Available since PostgreSQL-14
3604
+ */
3605
+ static VALUE
3606
+ pgconn_send_flush_request(VALUE self)
3607
+ {
3608
+ PGconn *conn = pg_get_pgconn(self);
3609
+ int res = PQsendFlushRequest(conn);
3610
+ if( res == 1 ) {
3611
+ return Qnil;
3612
+ } else {
3613
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3614
+ }
3615
+ }
3616
+
3617
+ #endif
3618
+
3415
3619
  /**************************************************************************
3416
3620
  * LARGE OBJECT SUPPORT
3417
3621
  **************************************************************************/
@@ -3600,7 +3804,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3600
3804
  return Qnil;
3601
3805
  }
3602
3806
 
3603
- str = rb_tainted_str_new(buffer, ret);
3807
+ str = rb_str_new(buffer, ret);
3604
3808
  xfree(buffer);
3605
3809
 
3606
3810
  return str;
@@ -3704,12 +3908,15 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3704
3908
  }
3705
3909
 
3706
3910
 
3707
- void
3911
+ static void
3708
3912
  pgconn_set_internal_encoding_index( VALUE self )
3709
3913
  {
3710
- PGconn *conn = pg_get_pgconn(self);
3711
- rb_encoding *enc = pg_conn_enc_get( conn );
3712
- PG_ENCODING_SET_NOCHECK( self, rb_enc_to_index(enc));
3914
+ int enc_idx;
3915
+ t_pg_connection *this = pg_get_connection_safe( self );
3916
+ rb_encoding *enc = pg_conn_enc_get( this->pgconn );
3917
+ enc_idx = rb_enc_to_index(enc);
3918
+ if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
3919
+ this->enc_idx = enc_idx;
3713
3920
  }
3714
3921
 
3715
3922
  /*
@@ -3752,13 +3959,12 @@ static VALUE pgconn_external_encoding(VALUE self);
3752
3959
  static VALUE
3753
3960
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3754
3961
  {
3755
- VALUE enc_inspect;
3756
3962
  if (NIL_P(enc)) {
3757
- pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3963
+ pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3758
3964
  return enc;
3759
3965
  }
3760
3966
  else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
3761
- pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3967
+ pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3762
3968
  return enc;
3763
3969
  }
3764
3970
  else {
@@ -3773,11 +3979,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3773
3979
  pgconn_set_internal_encoding_index( self );
3774
3980
  return enc;
3775
3981
  }
3776
-
3777
- enc_inspect = rb_inspect(enc);
3778
- rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
3779
-
3780
- return Qnil;
3781
3982
  }
3782
3983
 
3783
3984
 
@@ -3796,42 +3997,55 @@ pgconn_external_encoding(VALUE self)
3796
3997
  rb_encoding *enc = NULL;
3797
3998
  const char *pg_encname = NULL;
3798
3999
 
3799
- /* Use cached value if found */
3800
- if ( RTEST(this->external_encoding) ) return this->external_encoding;
3801
-
3802
4000
  pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
3803
4001
  enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
3804
- this->external_encoding = rb_enc_from_encoding( enc );
3805
-
3806
- return this->external_encoding;
4002
+ return rb_enc_from_encoding( enc );
3807
4003
  }
3808
4004
 
4005
+ /*
4006
+ * call-seq:
4007
+ * conn.set_client_encoding( encoding )
4008
+ *
4009
+ * Sets the client encoding to the _encoding_ String.
4010
+ */
4011
+ static VALUE
4012
+ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4013
+ {
4014
+ VALUE query_format, query;
4015
+
4016
+ Check_Type(encname, T_STRING);
4017
+ query_format = rb_str_new_cstr("set client_encoding to '%s'");
4018
+ query = rb_funcall(query_format, rb_intern("%"), 1, encname);
4019
+
4020
+ pgconn_async_exec(1, &query, self);
4021
+ pgconn_set_internal_encoding_index( self );
4022
+
4023
+ return Qnil;
4024
+ }
3809
4025
 
3810
4026
  static VALUE
3811
4027
  pgconn_set_client_encoding_async1( VALUE args )
3812
4028
  {
3813
4029
  VALUE self = ((VALUE*)args)[0];
3814
4030
  VALUE encname = ((VALUE*)args)[1];
3815
- VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3816
- VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3817
-
3818
- pgconn_async_exec(1, &query, self);
4031
+ pgconn_async_set_client_encoding(self, encname);
3819
4032
  return 0;
3820
4033
  }
3821
4034
 
3822
4035
 
3823
4036
  static VALUE
3824
- pgconn_set_client_encoding_async2( VALUE arg )
4037
+ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3825
4038
  {
3826
4039
  UNUSED(arg);
4040
+ UNUSED(ex);
3827
4041
  return 1;
3828
4042
  }
3829
4043
 
3830
4044
 
3831
4045
  static VALUE
3832
- pgconn_set_client_encoding_async( VALUE self, const char *encname )
4046
+ pgconn_set_client_encoding_async( VALUE self, VALUE encname )
3833
4047
  {
3834
- VALUE args[] = { self, rb_str_new_cstr(encname) };
4048
+ VALUE args[] = { self, encname };
3835
4049
  return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3836
4050
  }
3837
4051
 
@@ -3853,10 +4067,9 @@ pgconn_set_default_encoding( VALUE self )
3853
4067
 
3854
4068
  if (( enc = rb_default_internal_encoding() )) {
3855
4069
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3856
- if ( pgconn_set_client_encoding_async(self, encname) != 0 )
4070
+ if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
3857
4071
  rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
3858
4072
  encname, PQerrorMessage(conn) );
3859
- pgconn_set_internal_encoding_index( self );
3860
4073
  return rb_enc_from_encoding( enc );
3861
4074
  } else {
3862
4075
  pgconn_set_internal_encoding_index( self );
@@ -3878,12 +4091,12 @@ static VALUE
3878
4091
  pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
3879
4092
  {
3880
4093
  t_pg_connection *this = pg_get_connection( self );
4094
+ t_typemap *tm;
4095
+ UNUSED(tm);
4096
+
4097
+ /* Check type of method param */
4098
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3881
4099
 
3882
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3883
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3884
- rb_obj_classname( typemap ) );
3885
- }
3886
- Check_Type(typemap, T_DATA);
3887
4100
  this->type_map_for_queries = typemap;
3888
4101
 
3889
4102
  return typemap;
@@ -3918,12 +4131,10 @@ static VALUE
3918
4131
  pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
3919
4132
  {
3920
4133
  t_pg_connection *this = pg_get_connection( self );
4134
+ t_typemap *tm;
4135
+ UNUSED(tm);
3921
4136
 
3922
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3923
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3924
- rb_obj_classname( typemap ) );
3925
- }
3926
- Check_Type(typemap, T_DATA);
4137
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3927
4138
  this->type_map_for_results = typemap;
3928
4139
 
3929
4140
  return typemap;
@@ -3958,20 +4169,19 @@ pgconn_type_map_for_results_get(VALUE self)
3958
4169
  *
3959
4170
  */
3960
4171
  static VALUE
3961
- pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
4172
+ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
3962
4173
  {
3963
4174
  t_pg_connection *this = pg_get_connection( self );
3964
4175
 
3965
- if( typemap != Qnil ){
3966
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
3967
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
3968
- rb_obj_classname( typemap ) );
3969
- }
3970
- Check_Type(typemap, T_DATA);
4176
+ if( encoder != Qnil ){
4177
+ t_pg_coder *co;
4178
+ UNUSED(co);
4179
+ /* Check argument type */
4180
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
3971
4181
  }
3972
- this->encoder_for_put_copy_data = typemap;
4182
+ this->encoder_for_put_copy_data = encoder;
3973
4183
 
3974
- return typemap;
4184
+ return encoder;
3975
4185
  }
3976
4186
 
3977
4187
  /*
@@ -4007,20 +4217,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
4007
4217
  *
4008
4218
  */
4009
4219
  static VALUE
4010
- pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE typemap)
4220
+ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4011
4221
  {
4012
4222
  t_pg_connection *this = pg_get_connection( self );
4013
4223
 
4014
- if( typemap != Qnil ){
4015
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
4016
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
4017
- rb_obj_classname( typemap ) );
4018
- }
4019
- Check_Type(typemap, T_DATA);
4224
+ if( decoder != Qnil ){
4225
+ t_pg_coder *co;
4226
+ UNUSED(co);
4227
+ /* Check argument type */
4228
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
4020
4229
  }
4021
- this->decoder_for_get_copy_data = typemap;
4230
+ this->decoder_for_get_copy_data = decoder;
4022
4231
 
4023
- return typemap;
4232
+ return decoder;
4024
4233
  }
4025
4234
 
4026
4235
  /*
@@ -4045,16 +4254,54 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
4045
4254
 
4046
4255
  /*
4047
4256
  * call-seq:
4048
- * res.guess_result_memsize = enabled
4257
+ * conn.field_name_type = Symbol
4049
4258
  *
4050
- * This method is for testing only and will probably be removed in the future.
4259
+ * Set default type of field names of results retrieved by this connection.
4260
+ * It can be set to one of:
4261
+ * * +:string+ to use String based field names
4262
+ * * +:symbol+ to use Symbol based field names
4263
+ *
4264
+ * The default is +:string+ .
4265
+ *
4266
+ * Settings the type of field names affects only future results.
4267
+ *
4268
+ * See further description at PG::Result#field_name_type=
4269
+ *
4270
+ */
4271
+ static VALUE
4272
+ pgconn_field_name_type_set(VALUE self, VALUE sym)
4273
+ {
4274
+ t_pg_connection *this = pg_get_connection( self );
4275
+
4276
+ this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4277
+ if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4278
+ else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4279
+ else if ( sym == sym_string );
4280
+ else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4281
+
4282
+ return sym;
4283
+ }
4284
+
4285
+ /*
4286
+ * call-seq:
4287
+ * conn.field_name_type -> Symbol
4288
+ *
4289
+ * Get type of field names.
4290
+ *
4291
+ * See description at #field_name_type=
4051
4292
  */
4052
4293
  static VALUE
4053
- pgconn_guess_result_memsize_set(VALUE self, VALUE enable)
4294
+ pgconn_field_name_type_get(VALUE self)
4054
4295
  {
4055
4296
  t_pg_connection *this = pg_get_connection( self );
4056
- this->guess_result_memsize = RTEST(enable);
4057
- return enable;
4297
+
4298
+ if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4299
+ return sym_symbol;
4300
+ } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4301
+ return sym_static_symbol;
4302
+ } else {
4303
+ return sym_string;
4304
+ }
4058
4305
  }
4059
4306
 
4060
4307
 
@@ -4065,20 +4312,22 @@ void
4065
4312
  init_pg_connection()
4066
4313
  {
4067
4314
  s_id_encode = rb_intern("encode");
4315
+ s_id_autoclose_set = rb_intern("autoclose=");
4068
4316
  sym_type = ID2SYM(rb_intern("type"));
4069
4317
  sym_format = ID2SYM(rb_intern("format"));
4070
4318
  sym_value = ID2SYM(rb_intern("value"));
4319
+ sym_string = ID2SYM(rb_intern("string"));
4320
+ sym_symbol = ID2SYM(rb_intern("symbol"));
4321
+ sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
4071
4322
 
4072
4323
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4324
+ /* Help rdoc to known the Constants module */
4325
+ /* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
4073
4326
  rb_include_module(rb_cPGconn, rb_mPGconstants);
4074
4327
 
4075
4328
  /****** PG::Connection CLASS METHODS ******/
4076
4329
  rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
4077
4330
 
4078
- SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
4079
- SINGLETON_ALIAS(rb_cPGconn, "open", "new");
4080
- SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
4081
- SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
4082
4331
  rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4083
4332
  SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
4084
4333
  rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
@@ -4087,14 +4336,14 @@ init_pg_connection()
4087
4336
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4088
4337
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4089
4338
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4090
- rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
4339
+ rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4340
+ rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4091
4341
 
4092
4342
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
4093
- rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
4094
4343
  rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
4095
4344
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
4096
4345
  rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
4097
- rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
4346
+ rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
4098
4347
  rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
4099
4348
  rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
4100
4349
  rb_define_alias(rb_cPGconn, "close", "finish");
@@ -4106,9 +4355,7 @@ init_pg_connection()
4106
4355
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4107
4356
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4108
4357
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4109
- #ifdef HAVE_PQCONNINFO
4110
4358
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
4111
- #endif
4112
4359
  rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
4113
4360
  rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
4114
4361
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
@@ -4119,17 +4366,34 @@ init_pg_connection()
4119
4366
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
4120
4367
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
4121
4368
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4369
+ rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
4122
4370
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
4123
4371
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
4124
4372
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
4125
4373
 
4126
4374
  /****** PG::Connection INSTANCE METHODS: Command Execution ******/
4127
- rb_define_method(rb_cPGconn, "sync_exec", pgconn_exec, -1);
4128
- rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_exec_params, -1);
4129
- rb_define_method(rb_cPGconn, "sync_prepare", pgconn_prepare, -1);
4130
- rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_exec_prepared, -1);
4131
- rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_describe_prepared, 1);
4132
- rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_describe_portal, 1);
4375
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
4376
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
4377
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
4378
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4379
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4380
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4381
+
4382
+ rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4383
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
4384
+ rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
4385
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4386
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4387
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4388
+
4389
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
4390
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4391
+ rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
4392
+ rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
4393
+ rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4394
+ rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4395
+ rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4396
+
4133
4397
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
4134
4398
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4135
4399
  rb_define_alias(rb_cPGconn, "escape", "escape_string");
@@ -4142,42 +4406,38 @@ init_pg_connection()
4142
4406
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
4143
4407
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
4144
4408
  rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
4145
- rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
4146
- rb_define_method(rb_cPGconn, "async_exec_params", pgconn_async_exec_params, -1);
4147
- rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4148
4409
  rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
4149
- rb_define_method(rb_cPGconn, "async_prepare", pgconn_async_prepare, -1);
4150
4410
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
4151
- rb_define_method(rb_cPGconn, "async_exec_prepared", pgconn_async_exec_prepared, -1);
4152
4411
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
4153
- rb_define_method(rb_cPGconn, "async_describe_prepared", pgconn_async_describe_prepared, 1);
4154
4412
  rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
4155
- rb_define_method(rb_cPGconn, "async_describe_portal", pgconn_async_describe_portal, 1);
4156
- rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
4413
+ rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
4157
4414
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4158
4415
  rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
4159
- rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
4160
- rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
4161
- rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
4162
- rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
4416
+ rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
4417
+ rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
4418
+ rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
4419
+ rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
4420
+ rb_define_alias(rb_cPGconn, "async_flush", "flush");
4163
4421
  rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4164
4422
 
4165
4423
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4166
- rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
4424
+ rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4167
4425
 
4168
4426
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4169
4427
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
4170
4428
 
4171
4429
  /****** PG::Connection INSTANCE METHODS: COPY ******/
4172
- rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, -1);
4173
- rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
4174
- rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
4430
+ rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
4431
+ rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
4432
+ rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
4175
4433
 
4176
4434
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4177
4435
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4436
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4437
+ rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4438
+ #endif
4178
4439
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
4179
4440
  rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
4180
- rb_define_method(rb_cPGconn, "guess_result_memsize=", pgconn_guess_result_memsize_set, 1);
4181
4441
 
4182
4442
  /****** PG::Connection INSTANCE METHODS: Notice Processing ******/
4183
4443
  rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
@@ -4185,16 +4445,20 @@ init_pg_connection()
4185
4445
 
4186
4446
  /****** PG::Connection INSTANCE METHODS: Other ******/
4187
4447
  rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
4188
- rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
4448
+ rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
4449
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
4450
+ rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
4189
4451
  rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
4190
- rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
4191
4452
  rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
4453
+ rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
4192
4454
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
4193
4455
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
4194
4456
  rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4195
- rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
4457
+ rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4458
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4459
+ rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4196
4460
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
4197
- rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
4461
+ rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4198
4462
  #endif
4199
4463
 
4200
4464
  #ifdef HAVE_PQSSLATTRIBUTE
@@ -4203,6 +4467,14 @@ init_pg_connection()
4203
4467
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4204
4468
  #endif
4205
4469
 
4470
+ #ifdef HAVE_PQENTERPIPELINEMODE
4471
+ rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4472
+ rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4473
+ rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4474
+ rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
4475
+ rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4476
+ #endif
4477
+
4206
4478
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
4207
4479
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
4208
4480
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
@@ -4244,5 +4516,7 @@ init_pg_connection()
4244
4516
  rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
4245
4517
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
4246
4518
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
4247
- }
4248
4519
 
4520
+ rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
4521
+ rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
4522
+ }