pg 1.1.3 → 1.4.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (118) 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 +291 -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.rb +0 -0
  26. data/ext/errorcodes.txt +21 -2
  27. data/ext/extconf.rb +101 -26
  28. data/ext/gvl_wrappers.c +4 -0
  29. data/ext/gvl_wrappers.h +23 -0
  30. data/ext/pg.c +190 -122
  31. data/ext/pg.h +43 -17
  32. data/ext/pg_binary_decoder.c +20 -16
  33. data/ext/pg_binary_encoder.c +13 -12
  34. data/ext/pg_coder.c +95 -29
  35. data/ext/pg_connection.c +1214 -919
  36. data/ext/pg_copy_coder.c +50 -18
  37. data/ext/pg_record_coder.c +521 -0
  38. data/ext/pg_result.c +344 -153
  39. data/ext/pg_text_decoder.c +15 -9
  40. data/ext/pg_text_encoder.c +185 -53
  41. data/ext/pg_tuple.c +63 -35
  42. data/ext/pg_type_map.c +42 -9
  43. data/ext/pg_type_map_all_strings.c +19 -5
  44. data/ext/pg_type_map_by_class.c +54 -24
  45. data/ext/pg_type_map_by_column.c +73 -34
  46. data/ext/pg_type_map_by_mri_type.c +48 -19
  47. data/ext/pg_type_map_by_oid.c +55 -25
  48. data/ext/pg_type_map_in_ruby.c +51 -20
  49. data/ext/{util.c → pg_util.c} +7 -7
  50. data/ext/{util.h → pg_util.h} +0 -0
  51. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  52. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  53. data/lib/pg/basic_type_map_for_results.rb +81 -0
  54. data/lib/pg/basic_type_registry.rb +301 -0
  55. data/lib/pg/binary_decoder.rb +1 -0
  56. data/lib/pg/coder.rb +23 -2
  57. data/lib/pg/connection.rb +669 -71
  58. data/lib/pg/constants.rb +1 -0
  59. data/lib/pg/exceptions.rb +8 -1
  60. data/lib/pg/result.rb +13 -1
  61. data/lib/pg/text_decoder.rb +2 -3
  62. data/lib/pg/text_encoder.rb +8 -18
  63. data/lib/pg/type_map_by_column.rb +2 -1
  64. data/lib/pg/version.rb +4 -0
  65. data/lib/pg.rb +48 -33
  66. data/misc/openssl-pg-segfault.rb +31 -0
  67. data/misc/postgres/History.txt +9 -0
  68. data/misc/postgres/Manifest.txt +5 -0
  69. data/misc/postgres/README.txt +21 -0
  70. data/misc/postgres/Rakefile +21 -0
  71. data/misc/postgres/lib/postgres.rb +16 -0
  72. data/misc/ruby-pg/History.txt +9 -0
  73. data/misc/ruby-pg/Manifest.txt +5 -0
  74. data/misc/ruby-pg/README.txt +21 -0
  75. data/misc/ruby-pg/Rakefile +21 -0
  76. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  77. data/pg.gemspec +32 -0
  78. data/rakelib/task_extension.rb +46 -0
  79. data/sample/array_insert.rb +20 -0
  80. data/sample/async_api.rb +102 -0
  81. data/sample/async_copyto.rb +39 -0
  82. data/sample/async_mixed.rb +56 -0
  83. data/sample/check_conn.rb +21 -0
  84. data/sample/copydata.rb +71 -0
  85. data/sample/copyfrom.rb +81 -0
  86. data/sample/copyto.rb +19 -0
  87. data/sample/cursor.rb +21 -0
  88. data/sample/disk_usage_report.rb +177 -0
  89. data/sample/issue-119.rb +94 -0
  90. data/sample/losample.rb +69 -0
  91. data/sample/minimal-testcase.rb +17 -0
  92. data/sample/notify_wait.rb +72 -0
  93. data/sample/pg_statistics.rb +285 -0
  94. data/sample/replication_monitor.rb +222 -0
  95. data/sample/test_binary_values.rb +33 -0
  96. data/sample/wal_shipper.rb +434 -0
  97. data/sample/warehouse_partitions.rb +311 -0
  98. data.tar.gz.sig +0 -0
  99. metadata +94 -237
  100. metadata.gz.sig +0 -0
  101. data/ChangeLog +0 -6595
  102. data/lib/pg/basic_type_mapping.rb +0 -459
  103. data/spec/data/expected_trace.out +0 -26
  104. data/spec/data/random_binary_data +0 -0
  105. data/spec/helpers.rb +0 -381
  106. data/spec/pg/basic_type_mapping_spec.rb +0 -508
  107. data/spec/pg/connection_spec.rb +0 -1849
  108. data/spec/pg/connection_sync_spec.rb +0 -41
  109. data/spec/pg/result_spec.rb +0 -491
  110. data/spec/pg/tuple_spec.rb +0 -280
  111. data/spec/pg/type_map_by_class_spec.rb +0 -138
  112. data/spec/pg/type_map_by_column_spec.rb +0 -222
  113. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  114. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  115. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  116. data/spec/pg/type_map_spec.rb +0 -22
  117. data/spec/pg/type_spec.rb +0 -949
  118. 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,19 +12,44 @@
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;
27
+ static VALUE pgconn_async_flush(VALUE self);
23
28
 
24
29
  /*
25
30
  * Global functions
26
31
  */
27
32
 
33
+ /*
34
+ * Convenience function to raise connection errors
35
+ */
36
+ #ifdef __GNUC__
37
+ __attribute__((format(printf, 3, 4)))
38
+ #endif
39
+ static void
40
+ pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
41
+ {
42
+ VALUE msg, error;
43
+ va_list ap;
44
+
45
+ va_start(ap, format);
46
+ msg = rb_vsprintf(format, ap);
47
+ va_end(ap);
48
+ error = rb_exc_new_str(klass, msg);
49
+ rb_iv_set(error, "@connection", self);
50
+ rb_exc_raise(error);
51
+ }
52
+
28
53
  /*
29
54
  * Fetch the PG::Connection object data pointer.
30
55
  */
@@ -32,7 +57,7 @@ t_pg_connection *
32
57
  pg_get_connection( VALUE self )
33
58
  {
34
59
  t_pg_connection *this;
35
- Data_Get_Struct( self, t_pg_connection, this);
60
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
36
61
 
37
62
  return this;
38
63
  }
@@ -45,10 +70,10 @@ static t_pg_connection *
45
70
  pg_get_connection_safe( VALUE self )
46
71
  {
47
72
  t_pg_connection *this;
48
- Data_Get_Struct( self, t_pg_connection, this);
73
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
49
74
 
50
75
  if ( !this->pgconn )
51
- rb_raise( rb_eConnectionBad, "connection is closed" );
76
+ pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
52
77
 
53
78
  return this;
54
79
  }
@@ -64,10 +89,11 @@ PGconn *
64
89
  pg_get_pgconn( VALUE self )
65
90
  {
66
91
  t_pg_connection *this;
67
- Data_Get_Struct( self, t_pg_connection, this);
92
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
68
93
 
69
- if ( !this->pgconn )
70
- rb_raise( rb_eConnectionBad, "connection is closed" );
94
+ if ( !this->pgconn ){
95
+ pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
96
+ }
71
97
 
72
98
  return this->pgconn;
73
99
  }
@@ -85,10 +111,8 @@ pgconn_close_socket_io( VALUE self )
85
111
 
86
112
  if ( RTEST(socket_io) ) {
87
113
  #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) ){
90
- rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
91
- }
114
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) )
115
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
92
116
  #endif
93
117
  rb_funcall( socket_io, rb_intern("close"), 0 );
94
118
  }
@@ -145,17 +169,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
145
169
  * GC Mark function
146
170
  */
147
171
  static void
148
- pgconn_gc_mark( t_pg_connection *this )
172
+ pgconn_gc_mark( void *_this )
173
+ {
174
+ t_pg_connection *this = (t_pg_connection *)_this;
175
+ rb_gc_mark_movable( this->socket_io );
176
+ rb_gc_mark_movable( this->notice_receiver );
177
+ rb_gc_mark_movable( this->notice_processor );
178
+ rb_gc_mark_movable( this->type_map_for_queries );
179
+ rb_gc_mark_movable( this->type_map_for_results );
180
+ rb_gc_mark_movable( this->trace_stream );
181
+ rb_gc_mark_movable( this->encoder_for_put_copy_data );
182
+ rb_gc_mark_movable( this->decoder_for_get_copy_data );
183
+ }
184
+
185
+ static void
186
+ pgconn_gc_compact( void *_this )
149
187
  {
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 );
188
+ t_pg_connection *this = (t_pg_connection *)_this;
189
+ pg_gc_location( this->socket_io );
190
+ pg_gc_location( this->notice_receiver );
191
+ pg_gc_location( this->notice_processor );
192
+ pg_gc_location( this->type_map_for_queries );
193
+ pg_gc_location( this->type_map_for_results );
194
+ pg_gc_location( this->trace_stream );
195
+ pg_gc_location( this->encoder_for_put_copy_data );
196
+ pg_gc_location( this->decoder_for_get_copy_data );
159
197
  }
160
198
 
161
199
 
@@ -163,14 +201,45 @@ pgconn_gc_mark( t_pg_connection *this )
163
201
  * GC Free function
164
202
  */
165
203
  static void
166
- pgconn_gc_free( t_pg_connection *this )
204
+ pgconn_gc_free( void *_this )
167
205
  {
206
+ t_pg_connection *this = (t_pg_connection *)_this;
207
+ #if defined(_WIN32)
208
+ if ( RTEST(this->socket_io) ) {
209
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
210
+ rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
211
+ }
212
+ }
213
+ #endif
168
214
  if (this->pgconn != NULL)
169
215
  PQfinish( this->pgconn );
170
216
 
171
217
  xfree(this);
172
218
  }
173
219
 
220
+ /*
221
+ * Object Size function
222
+ */
223
+ static size_t
224
+ pgconn_memsize( const void *_this )
225
+ {
226
+ const t_pg_connection *this = (const t_pg_connection *)_this;
227
+ return sizeof(*this);
228
+ }
229
+
230
+ static const rb_data_type_t pg_connection_type = {
231
+ "PG::Connection",
232
+ {
233
+ pgconn_gc_mark,
234
+ pgconn_gc_free,
235
+ pgconn_memsize,
236
+ pg_compact_callback(pgconn_gc_compact),
237
+ },
238
+ 0,
239
+ 0,
240
+ 0,
241
+ };
242
+
174
243
 
175
244
  /**************************************************************************
176
245
  * Class Methods
@@ -186,7 +255,7 @@ static VALUE
186
255
  pgconn_s_allocate( VALUE klass )
187
256
  {
188
257
  t_pg_connection *this;
189
- VALUE self = Data_Make_Struct( klass, t_pg_connection, pgconn_gc_mark, pgconn_gc_free, this );
258
+ VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
190
259
 
191
260
  this->pgconn = NULL;
192
261
  this->socket_io = Qnil;
@@ -197,89 +266,27 @@ pgconn_s_allocate( VALUE klass )
197
266
  this->encoder_for_put_copy_data = Qnil;
198
267
  this->decoder_for_get_copy_data = Qnil;
199
268
  this->trace_stream = Qnil;
200
- this->external_encoding = Qnil;
201
- this->guess_result_memsize = 1;
269
+ rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
202
270
 
203
271
  return self;
204
272
  }
205
273
 
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
274
  static VALUE
265
- pgconn_init(int argc, VALUE *argv, VALUE self)
275
+ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
266
276
  {
267
277
  t_pg_connection *this;
268
278
  VALUE conninfo;
269
- VALUE error;
279
+ VALUE self = pgconn_s_allocate( klass );
270
280
 
271
281
  this = pg_get_connection( self );
272
282
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
273
283
  this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
274
284
 
275
285
  if(this->pgconn == NULL)
276
- rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
286
+ rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
277
287
 
278
- if (PQstatus(this->pgconn) == CONNECTION_BAD) {
279
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
280
- rb_iv_set(error, "@connection", self);
281
- rb_exc_raise(error);
282
- }
288
+ if (PQstatus(this->pgconn) == CONNECTION_BAD)
289
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
283
290
 
284
291
  pgconn_set_default_encoding( self );
285
292
 
@@ -295,14 +302,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
295
302
  * PG::Connection.connect_start(connection_string) -> conn
296
303
  * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
297
304
  *
298
- * This is an asynchronous version of PG::Connection.connect().
305
+ * This is an asynchronous version of PG::Connection.new.
299
306
  *
300
307
  * Use #connect_poll to poll the status of the connection.
301
308
  *
302
309
  * 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,
310
+ * +Encoding.default_internal+ is set. To set it after the connection is established,
304
311
  * call #internal_encoding=. You can also set it automatically by setting
305
- * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
312
+ * <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
313
+ *
314
+ * 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
315
  *
307
316
  */
308
317
  static VALUE
@@ -310,7 +319,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
310
319
  {
311
320
  VALUE rb_conn;
312
321
  VALUE conninfo;
313
- VALUE error;
314
322
  t_pg_connection *this;
315
323
 
316
324
  /*
@@ -323,13 +331,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
323
331
  this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
324
332
 
325
333
  if( this->pgconn == NULL )
326
- rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
334
+ rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
327
335
 
328
- if ( PQstatus(this->pgconn) == CONNECTION_BAD ) {
329
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
330
- rb_iv_set(error, "@connection", rb_conn);
331
- rb_exc_raise(error);
332
- }
336
+ if ( PQstatus(this->pgconn) == CONNECTION_BAD )
337
+ pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
333
338
 
334
339
  if ( rb_block_given_p() ) {
335
340
  return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
@@ -337,34 +342,14 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
337
342
  return rb_conn;
338
343
  }
339
344
 
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
345
  static VALUE
361
- pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
346
+ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
362
347
  {
363
348
  PGPing ping;
364
349
  VALUE conninfo;
365
350
 
366
351
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
367
- ping = PQping( StringValueCStr(conninfo) );
352
+ ping = gvl_PQping( StringValueCStr(conninfo) );
368
353
 
369
354
  return INT2FIX((int)ping);
370
355
  }
@@ -405,31 +390,40 @@ pgconn_s_conndefaults(VALUE self)
405
390
  return array;
406
391
  }
407
392
 
408
-
409
- #ifdef HAVE_PQENCRYPTPASSWORDCONN
410
393
  /*
411
- * call-seq:
412
- * conn.encrypt_password( password, username, algorithm=nil ) -> String
394
+ * Document-method: PG::Connection.conninfo_parse
413
395
  *
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.
396
+ * call-seq:
397
+ * PG::Connection.conninfo_parse(conninfo_string) -> Array
428
398
  *
429
- * Available since PostgreSQL-10
399
+ * Returns parsed connection options from the provided connection string as an array of hashes.
400
+ * Each hash has the same keys as PG::Connection.conndefaults() .
401
+ * The values from the +conninfo_string+ are stored in the +:val+ key.
430
402
  */
431
403
  static VALUE
432
- pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
404
+ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
405
+ {
406
+ VALUE array;
407
+ char *errmsg = NULL;
408
+ PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
409
+ if(errmsg){
410
+ VALUE error = rb_str_new_cstr(errmsg);
411
+ PQfreemem(errmsg);
412
+ rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
413
+ }
414
+ array = pgconn_make_conninfo_array( options );
415
+
416
+ PQconninfoFree(options);
417
+
418
+ UNUSED( self );
419
+
420
+ return array;
421
+ }
422
+
423
+
424
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
425
+ static VALUE
426
+ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
433
427
  {
434
428
  char *encrypted = NULL;
435
429
  VALUE rval = Qnil;
@@ -445,12 +439,8 @@ pgconn_encrypt_password(int argc, VALUE *argv, VALUE self)
445
439
  if ( encrypted ) {
446
440
  rval = rb_str_new2( encrypted );
447
441
  PQfreemem( encrypted );
448
-
449
- OBJ_INFECT( rval, password );
450
- OBJ_INFECT( rval, username );
451
- OBJ_INFECT( rval, algorithm );
452
442
  } else {
453
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
443
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
454
444
  }
455
445
 
456
446
  return rval;
@@ -481,9 +471,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
481
471
  rval = rb_str_new2( encrypted );
482
472
  PQfreemem( encrypted );
483
473
 
484
- OBJ_INFECT( rval, password );
485
- OBJ_INFECT( rval, username );
486
-
487
474
  return rval;
488
475
  }
489
476
 
@@ -507,17 +494,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
507
494
  * the asynchronous connection is ready
508
495
  *
509
496
  * Example:
510
- * conn = PG::Connection.connect_start("dbname=mydatabase")
511
- * socket = conn.socket_io
497
+ * require "io/wait"
498
+ *
499
+ * conn = PG::Connection.connect_start(dbname: 'mydatabase')
512
500
  * status = conn.connect_poll
513
501
  * while(status != PG::PGRES_POLLING_OK) do
514
502
  * # do some work while waiting for the connection to complete
515
503
  * if(status == PG::PGRES_POLLING_READING)
516
- * if(not select([socket], [], [], 10.0))
504
+ * unless conn.socket_io.wait_readable(10.0)
517
505
  * raise "Asynchronous connection timed out!"
518
506
  * end
519
507
  * elsif(status == PG::PGRES_POLLING_WRITING)
520
- * if(not select([], [socket], [], 10.0))
508
+ * unless conn.socket_io.wait_writable(10.0)
521
509
  * raise "Asynchronous connection timed out!"
522
510
  * end
523
511
  * end
@@ -531,6 +519,9 @@ pgconn_connect_poll(VALUE self)
531
519
  {
532
520
  PostgresPollingStatusType status;
533
521
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
522
+
523
+ pgconn_close_socket_io(self);
524
+
534
525
  return INT2FIX((int)status);
535
526
  }
536
527
 
@@ -567,15 +558,8 @@ pgconn_finished_p( VALUE self )
567
558
  }
568
559
 
569
560
 
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
561
  static VALUE
578
- pgconn_reset( VALUE self )
562
+ pgconn_sync_reset( VALUE self )
579
563
  {
580
564
  pgconn_close_socket_io( self );
581
565
  gvl_PQreset( pg_get_pgconn(self) );
@@ -597,7 +581,7 @@ pgconn_reset_start(VALUE self)
597
581
  {
598
582
  pgconn_close_socket_io( self );
599
583
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
600
- rb_raise(rb_eUnableToSend, "reset has failed");
584
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
601
585
  return Qnil;
602
586
  }
603
587
 
@@ -614,6 +598,9 @@ pgconn_reset_poll(VALUE self)
614
598
  {
615
599
  PostgresPollingStatusType status;
616
600
  status = gvl_PQresetPoll(pg_get_pgconn(self));
601
+
602
+ pgconn_close_socket_io(self);
603
+
617
604
  return INT2FIX((int)status);
618
605
  }
619
606
 
@@ -629,7 +616,7 @@ pgconn_db(VALUE self)
629
616
  {
630
617
  char *db = PQdb(pg_get_pgconn(self));
631
618
  if (!db) return Qnil;
632
- return rb_tainted_str_new2(db);
619
+ return rb_str_new2(db);
633
620
  }
634
621
 
635
622
  /*
@@ -643,7 +630,7 @@ pgconn_user(VALUE self)
643
630
  {
644
631
  char *user = PQuser(pg_get_pgconn(self));
645
632
  if (!user) return Qnil;
646
- return rb_tainted_str_new2(user);
633
+ return rb_str_new2(user);
647
634
  }
648
635
 
649
636
  /*
@@ -657,22 +644,53 @@ pgconn_pass(VALUE self)
657
644
  {
658
645
  char *user = PQpass(pg_get_pgconn(self));
659
646
  if (!user) return Qnil;
660
- return rb_tainted_str_new2(user);
647
+ return rb_str_new2(user);
661
648
  }
662
649
 
663
650
  /*
664
651
  * call-seq:
665
652
  * conn.host()
666
653
  *
667
- * Returns the connected server name.
654
+ * Returns the server host name of the active connection.
655
+ * This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
656
+ * (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
657
+ *
658
+ * If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
659
+ * If only hostaddr was specified, then that is returned.
660
+ * If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
661
+ *
662
+ * If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
663
+ *
664
+ * If multiple hosts were specified in the connection parameters, it is not possible to rely on the result of +host+ until the connection is established.
665
+ * The status of the connection can be checked using the function Connection#status .
668
666
  */
669
667
  static VALUE
670
668
  pgconn_host(VALUE self)
671
669
  {
672
670
  char *host = PQhost(pg_get_pgconn(self));
673
671
  if (!host) return Qnil;
674
- return rb_tainted_str_new2(host);
672
+ return rb_str_new2(host);
673
+ }
674
+
675
+ /* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
676
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
677
+ /*
678
+ * call-seq:
679
+ * conn.hostaddr()
680
+ *
681
+ * Returns the server IP address of the active connection.
682
+ * This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
683
+ * If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
684
+ *
685
+ */
686
+ static VALUE
687
+ pgconn_hostaddr(VALUE self)
688
+ {
689
+ char *host = PQhostaddr(pg_get_pgconn(self));
690
+ if (!host) return Qnil;
691
+ return rb_str_new2(host);
675
692
  }
693
+ #endif
676
694
 
677
695
  /*
678
696
  * call-seq:
@@ -684,21 +702,19 @@ static VALUE
684
702
  pgconn_port(VALUE self)
685
703
  {
686
704
  char* port = PQport(pg_get_pgconn(self));
687
- return INT2NUM(atol(port));
705
+ return INT2NUM(atoi(port));
688
706
  }
689
707
 
690
708
  /*
691
709
  * call-seq:
692
710
  * conn.tty()
693
711
  *
694
- * Returns the connected pgtty. (Obsolete)
712
+ * Obsolete function.
695
713
  */
696
714
  static VALUE
697
715
  pgconn_tty(VALUE self)
698
716
  {
699
- char *tty = PQtty(pg_get_pgconn(self));
700
- if (!tty) return Qnil;
701
- return rb_tainted_str_new2(tty);
717
+ return rb_str_new2("");
702
718
  }
703
719
 
704
720
  /*
@@ -712,11 +728,10 @@ pgconn_options(VALUE self)
712
728
  {
713
729
  char *options = PQoptions(pg_get_pgconn(self));
714
730
  if (!options) return Qnil;
715
- return rb_tainted_str_new2(options);
731
+ return rb_str_new2(options);
716
732
  }
717
733
 
718
734
 
719
- #ifdef HAVE_PQCONNINFO
720
735
  /*
721
736
  * call-seq:
722
737
  * conn.conninfo -> hash
@@ -736,14 +751,20 @@ pgconn_conninfo( VALUE self )
736
751
 
737
752
  return array;
738
753
  }
739
- #endif
740
754
 
741
755
 
742
756
  /*
743
757
  * call-seq:
744
758
  * conn.status()
745
759
  *
746
- * Returns status of connection : CONNECTION_OK or CONNECTION_BAD
760
+ * Returns the status of the connection, which is one:
761
+ * PG::Constants::CONNECTION_OK
762
+ * PG::Constants::CONNECTION_BAD
763
+ *
764
+ * ... and other constants of kind PG::Constants::CONNECTION_*
765
+ *
766
+ * Example:
767
+ * PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
747
768
  */
748
769
  static VALUE
749
770
  pgconn_status(VALUE self)
@@ -793,7 +814,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
793
814
  if(ret == NULL)
794
815
  return Qnil;
795
816
  else
796
- return rb_tainted_str_new2(ret);
817
+ return rb_str_new2(ret);
797
818
  }
798
819
 
799
820
  /*
@@ -831,14 +852,17 @@ pgconn_server_version(VALUE self)
831
852
  * call-seq:
832
853
  * conn.error_message -> String
833
854
  *
834
- * Returns the error message about connection.
855
+ * Returns the error message most recently generated by an operation on the connection.
856
+ *
857
+ * Nearly all libpq functions will set a message for conn.error_message if they fail.
858
+ * Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
835
859
  */
836
860
  static VALUE
837
861
  pgconn_error_message(VALUE self)
838
862
  {
839
863
  char *error = PQerrorMessage(pg_get_pgconn(self));
840
864
  if (!error) return Qnil;
841
- return rb_tainted_str_new2(error);
865
+ return rb_str_new2(error);
842
866
  }
843
867
 
844
868
  /*
@@ -862,8 +886,11 @@ static VALUE
862
886
  pgconn_socket(VALUE self)
863
887
  {
864
888
  int sd;
889
+ pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
890
+
865
891
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
866
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
892
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
893
+
867
894
  return INT2NUM(sd);
868
895
  }
869
896
 
@@ -871,37 +898,45 @@ pgconn_socket(VALUE self)
871
898
  * call-seq:
872
899
  * conn.socket_io() -> IO
873
900
  *
874
- * Fetch a memorized IO object created from the Connection's underlying socket.
875
- * This object can be used for IO.select to wait for events while running
876
- * asynchronous API calls.
901
+ * Fetch an IO object created from the Connection's underlying socket.
902
+ * This object can be used per <tt>socket_io.wait_readable</tt>, <tt>socket_io.wait_writable</tt> or for <tt>IO.select</tt> to wait for events while running asynchronous API calls.
903
+ * <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
904
+ *
905
+ * The IO object can change while the connection is established, but is memorized afterwards.
906
+ * So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
877
907
  *
878
- * Using this instead of #socket avoids the problem of the underlying connection
879
- * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
880
- * goes out of scope. In contrast to #socket, it also works on Windows.
908
+ * Using this method also works on Windows in contrast to using #socket .
909
+ * It also avoids the problem of the underlying connection being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt> goes out of scope.
881
910
  */
882
911
  static VALUE
883
912
  pgconn_socket_io(VALUE self)
884
913
  {
885
914
  int sd;
886
915
  int ruby_sd;
887
- ID id_autoclose = rb_intern("autoclose=");
888
916
  t_pg_connection *this = pg_get_connection_safe( self );
917
+ VALUE cSocket;
889
918
  VALUE socket_io = this->socket_io;
890
919
 
891
920
  if ( !RTEST(socket_io) ) {
892
- if( (sd = PQsocket(this->pgconn)) < 0)
893
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
921
+ if( (sd = PQsocket(this->pgconn)) < 0){
922
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
923
+ }
894
924
 
895
925
  #ifdef _WIN32
896
926
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
927
+ if( ruby_sd == -1 )
928
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
929
+
930
+ this->ruby_sd = ruby_sd;
897
931
  #else
898
932
  ruby_sd = sd;
899
933
  #endif
900
934
 
901
- socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
935
+ cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
936
+ socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
902
937
 
903
938
  /* Disable autoclose feature */
904
- rb_funcall( socket_io, id_autoclose, 1, Qfalse );
939
+ rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
905
940
 
906
941
  this->socket_io = socket_io;
907
942
  }
@@ -923,6 +958,51 @@ pgconn_backend_pid(VALUE self)
923
958
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
924
959
  }
925
960
 
961
+ typedef struct
962
+ {
963
+ struct sockaddr_storage addr;
964
+ socklen_t salen;
965
+ } SockAddr;
966
+
967
+ /* Copy of struct pg_cancel from libpq-int.h
968
+ *
969
+ * See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
970
+ */
971
+ struct pg_cancel
972
+ {
973
+ SockAddr raddr; /* Remote address */
974
+ int be_pid; /* PID of backend --- needed for cancels */
975
+ int be_key; /* key of backend --- needed for cancels */
976
+ };
977
+
978
+ /*
979
+ * call-seq:
980
+ * conn.backend_key() -> Integer
981
+ *
982
+ * Returns the key of the backend server process for this connection.
983
+ * This key can be used to cancel queries on the server.
984
+ */
985
+ static VALUE
986
+ pgconn_backend_key(VALUE self)
987
+ {
988
+ int be_key;
989
+ struct pg_cancel *cancel;
990
+ PGconn *conn = pg_get_pgconn(self);
991
+
992
+ cancel = (struct pg_cancel*)PQgetCancel(conn);
993
+ if(cancel == NULL)
994
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
995
+
996
+ if( cancel->be_pid != PQbackendPID(conn) )
997
+ rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
998
+
999
+ be_key = cancel->be_key;
1000
+
1001
+ PQfreeCancel(cancel);
1002
+
1003
+ return INT2NUM(be_key);
1004
+ }
1005
+
926
1006
  /*
927
1007
  * call-seq:
928
1008
  * conn.connection_needs_password() -> Boolean
@@ -953,36 +1033,27 @@ pgconn_connection_used_password(VALUE self)
953
1033
  /* :TODO: get_ssl */
954
1034
 
955
1035
 
956
- static VALUE pgconn_exec_params( int, VALUE *, VALUE );
1036
+ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
957
1037
 
958
1038
  /*
959
1039
  * 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.
1040
+ * conn.sync_exec(sql) -> PG::Result
1041
+ * conn.sync_exec(sql) {|pg_result| block }
966
1042
  *
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.
1043
+ * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
1044
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
970
1045
  *
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.
1046
+ * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
1047
+ * However #async_exec has two advantages:
974
1048
  *
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.
1049
+ * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
1050
+ * 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
1051
+ * So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
981
1052
  */
982
1053
  static VALUE
983
- pgconn_exec(int argc, VALUE *argv, VALUE self)
1054
+ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
984
1055
  {
985
- PGconn *conn = pg_get_pgconn(self);
1056
+ t_pg_connection *this = pg_get_connection_safe( self );
986
1057
  PGresult *result = NULL;
987
1058
  VALUE rb_pgresult;
988
1059
 
@@ -990,7 +1061,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
990
1061
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
991
1062
  VALUE query_str = argv[0];
992
1063
 
993
- result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
1064
+ result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
994
1065
  rb_pgresult = pg_new_result(result, self);
995
1066
  pg_result_check(rb_pgresult);
996
1067
  if (rb_block_given_p()) {
@@ -1001,7 +1072,7 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
1001
1072
  pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
1002
1073
 
1003
1074
  /* Otherwise, just call #exec_params instead for backward-compatibility */
1004
- return pgconn_exec_params( argc, argv, self );
1075
+ return pgconn_sync_exec_params( argc, argv, self );
1005
1076
 
1006
1077
  }
1007
1078
 
@@ -1033,7 +1104,7 @@ struct query_params_data {
1033
1104
  * Filled by alloc_query_params()
1034
1105
  */
1035
1106
 
1036
- /* Wraps the pointer of allocated memory, if function parameters dont't
1107
+ /* Wraps the pointer of allocated memory, if function parameters don't
1037
1108
  * fit in the memory_pool below.
1038
1109
  */
1039
1110
  VALUE heap_pool;
@@ -1051,7 +1122,7 @@ struct query_params_data {
1051
1122
  Oid *types;
1052
1123
 
1053
1124
  /* This array takes the string values for the timeframe of the query,
1054
- * if param value convertion is required
1125
+ * if param value conversion is required
1055
1126
  */
1056
1127
  VALUE gc_array;
1057
1128
 
@@ -1065,8 +1136,9 @@ struct query_params_data {
1065
1136
  };
1066
1137
 
1067
1138
  static void
1068
- free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1139
+ free_typecast_heap_chain(void *_chain_entry)
1069
1140
  {
1141
+ struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
1070
1142
  while(chain_entry){
1071
1143
  struct linked_typecast_data *next = chain_entry->next;
1072
1144
  xfree(chain_entry);
@@ -1074,6 +1146,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1074
1146
  }
1075
1147
  }
1076
1148
 
1149
+ static const rb_data_type_t pg_typecast_buffer_type = {
1150
+ "PG::Connection typecast buffer chain",
1151
+ {
1152
+ (RUBY_DATA_FUNC) NULL,
1153
+ free_typecast_heap_chain,
1154
+ (size_t (*)(const void *))NULL,
1155
+ },
1156
+ 0,
1157
+ 0,
1158
+ RUBY_TYPED_FREE_IMMEDIATELY,
1159
+ };
1160
+
1077
1161
  static char *
1078
1162
  alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1079
1163
  {
@@ -1084,17 +1168,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1084
1168
  /* Did we already wrap a memory chain per T_DATA object? */
1085
1169
  if( NIL_P( *typecast_heap_chain ) ){
1086
1170
  /* 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 );
1171
+ *typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
1088
1172
  allocated->next = NULL;
1089
1173
  } else {
1090
1174
  /* Append to the chain */
1091
- allocated->next = DATA_PTR( *typecast_heap_chain );
1092
- DATA_PTR( *typecast_heap_chain ) = allocated;
1175
+ allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
1176
+ RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
1093
1177
  }
1094
1178
 
1095
1179
  return &allocated->data[0];
1096
1180
  }
1097
1181
 
1182
+ static const rb_data_type_t pg_query_heap_pool_type = {
1183
+ "PG::Connection query heap pool",
1184
+ {
1185
+ (RUBY_DATA_FUNC) NULL,
1186
+ RUBY_TYPED_DEFAULT_FREE,
1187
+ (size_t (*)(const void *))NULL,
1188
+ },
1189
+ 0,
1190
+ 0,
1191
+ RUBY_TYPED_FREE_IMMEDIATELY,
1192
+ };
1098
1193
 
1099
1194
  static int
1100
1195
  alloc_query_params(struct query_params_data *paramsData)
@@ -1109,7 +1204,7 @@ alloc_query_params(struct query_params_data *paramsData)
1109
1204
 
1110
1205
  Check_Type(paramsData->params, T_ARRAY);
1111
1206
 
1112
- p_typemap = DATA_PTR( paramsData->typemap );
1207
+ p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
1113
1208
  p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
1114
1209
 
1115
1210
  paramsData->heap_pool = Qnil;
@@ -1128,7 +1223,7 @@ alloc_query_params(struct query_params_data *paramsData)
1128
1223
  /* Allocate one combined memory pool for all possible function parameters */
1129
1224
  memory_pool = (char*)xmalloc( required_pool_size );
1130
1225
  /* 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 );
1226
+ paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
1132
1227
  required_pool_size = 0;
1133
1228
  }else{
1134
1229
  /* Use stack memory for function parameters */
@@ -1241,68 +1336,33 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1241
1336
  /* Use default typemap for queries. It's type is checked when assigned. */
1242
1337
  paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
1243
1338
  }else{
1339
+ t_typemap *tm;
1340
+ UNUSED(tm);
1341
+
1244
1342
  /* 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 );
1343
+ TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
1250
1344
  }
1251
1345
  }
1252
1346
 
1253
1347
  /*
1254
1348
  * 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+.
1349
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1350
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1276
1351
  *
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.
1285
- *
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.
1352
+ * This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
1353
+ * See #async_exec for the differences between the two API variants.
1354
+ * 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
1355
  */
1296
1356
  static VALUE
1297
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1357
+ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1298
1358
  {
1299
- PGconn *conn = pg_get_pgconn(self);
1359
+ t_pg_connection *this = pg_get_connection_safe( self );
1300
1360
  PGresult *result = NULL;
1301
1361
  VALUE rb_pgresult;
1302
1362
  VALUE command, in_res_fmt;
1303
1363
  int nParams;
1304
1364
  int resultFormat;
1305
- struct query_params_data paramsData = { ENCODING_GET(self) };
1365
+ struct query_params_data paramsData = { this->enc_idx };
1306
1366
 
1307
1367
  /* For compatibility we accept 1 to 4 parameters */
1308
1368
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
@@ -1314,14 +1374,14 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1314
1374
  */
1315
1375
  if ( NIL_P(paramsData.params) ) {
1316
1376
  pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1317
- return pgconn_exec( 1, argv, self );
1377
+ return pgconn_sync_exec( 1, argv, self );
1318
1378
  }
1319
1379
  pgconn_query_assign_typemap( self, &paramsData );
1320
1380
 
1321
1381
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1322
1382
  nParams = alloc_query_params( &paramsData );
1323
1383
 
1324
- result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1384
+ result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1325
1385
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1326
1386
 
1327
1387
  free_query_params( &paramsData );
@@ -1338,28 +1398,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1338
1398
 
1339
1399
  /*
1340
1400
  * 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.
1346
- *
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.
1401
+ * conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1353
1402
  *
1354
- * For example: "SELECT $1::int"
1355
- *
1356
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1357
- * inside the SQL query.
1403
+ * This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
1404
+ * See #async_exec for the differences between the two API variants.
1405
+ * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1358
1406
  */
1359
1407
  static VALUE
1360
- pgconn_prepare(int argc, VALUE *argv, VALUE self)
1408
+ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1361
1409
  {
1362
- PGconn *conn = pg_get_pgconn(self);
1410
+ t_pg_connection *this = pg_get_connection_safe( self );
1363
1411
  PGresult *result = NULL;
1364
1412
  VALUE rb_pgresult;
1365
1413
  VALUE name, command, in_paramtypes;
@@ -1369,7 +1417,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1369
1417
  Oid *paramTypes = NULL;
1370
1418
  const char *name_cstr;
1371
1419
  const char *command_cstr;
1372
- int enc_idx = ENCODING_GET(self);
1420
+ int enc_idx = this->enc_idx;
1373
1421
 
1374
1422
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1375
1423
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1387,7 +1435,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1387
1435
  paramTypes[i] = NUM2UINT(param);
1388
1436
  }
1389
1437
  }
1390
- result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1438
+ result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1391
1439
 
1392
1440
  xfree(paramTypes);
1393
1441
 
@@ -1398,49 +1446,23 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1398
1446
 
1399
1447
  /*
1400
1448
  * 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.
1449
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1450
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1429
1451
  *
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.
1452
+ * This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
1453
+ * See #async_exec for the differences between the two API variants.
1454
+ * 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
1455
  */
1434
1456
  static VALUE
1435
- pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1457
+ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1436
1458
  {
1437
- PGconn *conn = pg_get_pgconn(self);
1459
+ t_pg_connection *this = pg_get_connection_safe( self );
1438
1460
  PGresult *result = NULL;
1439
1461
  VALUE rb_pgresult;
1440
1462
  VALUE name, in_res_fmt;
1441
1463
  int nParams;
1442
1464
  int resultFormat;
1443
- struct query_params_data paramsData = { ENCODING_GET(self) };
1465
+ struct query_params_data paramsData = { this->enc_idx };
1444
1466
 
1445
1467
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1446
1468
  paramsData.with_types = 0;
@@ -1453,7 +1475,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1453
1475
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1454
1476
  nParams = alloc_query_params( &paramsData );
1455
1477
 
1456
- result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1478
+ result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1457
1479
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1458
1480
  resultFormat);
1459
1481
 
@@ -1470,25 +1492,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1470
1492
 
1471
1493
  /*
1472
1494
  * call-seq:
1473
- * conn.describe_prepared( statement_name ) -> PG::Result
1495
+ * conn.sync_describe_prepared( statement_name ) -> PG::Result
1474
1496
  *
1475
- * Retrieve information about the prepared statement
1476
- * _statement_name_.
1497
+ * This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
1498
+ * See #async_exec for the differences between the two API variants.
1499
+ * 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
1500
  */
1478
1501
  static VALUE
1479
- pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1502
+ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1480
1503
  {
1481
1504
  PGresult *result;
1482
1505
  VALUE rb_pgresult;
1483
- PGconn *conn = pg_get_pgconn(self);
1506
+ t_pg_connection *this = pg_get_connection_safe( self );
1484
1507
  const char *stmt;
1485
1508
  if(NIL_P(stmt_name)) {
1486
1509
  stmt = NULL;
1487
1510
  }
1488
1511
  else {
1489
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1512
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1490
1513
  }
1491
- result = gvl_PQdescribePrepared(conn, stmt);
1514
+ result = gvl_PQdescribePrepared(this->pgconn, stmt);
1492
1515
  rb_pgresult = pg_new_result(result, self);
1493
1516
  pg_result_check(rb_pgresult);
1494
1517
  return rb_pgresult;
@@ -1497,25 +1520,27 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1497
1520
 
1498
1521
  /*
1499
1522
  * call-seq:
1500
- * conn.describe_portal( portal_name ) -> PG::Result
1523
+ * conn.sync_describe_portal( portal_name ) -> PG::Result
1501
1524
  *
1502
- * Retrieve information about the portal _portal_name_.
1525
+ * This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
1526
+ * See #async_exec for the differences between the two API variants.
1527
+ * 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
1528
  */
1504
1529
  static VALUE
1505
- pgconn_describe_portal(self, stmt_name)
1530
+ pgconn_sync_describe_portal(self, stmt_name)
1506
1531
  VALUE self, stmt_name;
1507
1532
  {
1508
1533
  PGresult *result;
1509
1534
  VALUE rb_pgresult;
1510
- PGconn *conn = pg_get_pgconn(self);
1535
+ t_pg_connection *this = pg_get_connection_safe( self );
1511
1536
  const char *stmt;
1512
1537
  if(NIL_P(stmt_name)) {
1513
1538
  stmt = NULL;
1514
1539
  }
1515
1540
  else {
1516
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1541
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1517
1542
  }
1518
- result = gvl_PQdescribePortal(conn, stmt);
1543
+ result = gvl_PQdescribePortal(this->pgconn, stmt);
1519
1544
  rb_pgresult = pg_new_result(result, self);
1520
1545
  pg_result_check(rb_pgresult);
1521
1546
  return rb_pgresult;
@@ -1537,6 +1562,9 @@ pgconn_describe_portal(self, stmt_name)
1537
1562
  * * +PGRES_NONFATAL_ERROR+
1538
1563
  * * +PGRES_FATAL_ERROR+
1539
1564
  * * +PGRES_COPY_BOTH+
1565
+ * * +PGRES_SINGLE_TUPLE+
1566
+ * * +PGRES_PIPELINE_SYNC+
1567
+ * * +PGRES_PIPELINE_ABORTED+
1540
1568
  */
1541
1569
  static VALUE
1542
1570
  pgconn_make_empty_pgresult(VALUE self, VALUE status)
@@ -1562,13 +1590,15 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1562
1590
  * Consider using exec_params, which avoids the need for passing values
1563
1591
  * inside of SQL commands.
1564
1592
  *
1565
- * Encoding of escaped string will be equal to client encoding of connection.
1593
+ * Character encoding of escaped string will be equal to client encoding of connection.
1566
1594
  *
1567
1595
  * NOTE: This class version of this method can only be used safely in client
1568
1596
  * programs that use a single PostgreSQL connection at a time (in this case it can
1569
1597
  * find out what it needs to know "behind the scenes"). It might give the wrong
1570
1598
  * results if used in programs that use multiple database connections; use the
1571
1599
  * same method on the connection object in such cases.
1600
+ *
1601
+ * See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
1572
1602
  */
1573
1603
  static VALUE
1574
1604
  pgconn_s_escape(VALUE self, VALUE string)
@@ -1580,7 +1610,7 @@ pgconn_s_escape(VALUE self, VALUE string)
1580
1610
  int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1581
1611
 
1582
1612
  StringValueCStr(string);
1583
- enc_idx = ENCODING_GET( singleton ? string : self );
1613
+ enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
1584
1614
  if( ENCODING_GET(string) != enc_idx ){
1585
1615
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1586
1616
  }
@@ -1590,14 +1620,13 @@ pgconn_s_escape(VALUE self, VALUE string)
1590
1620
  if( !singleton ) {
1591
1621
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1592
1622
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1593
- if(error) {
1594
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1595
- }
1623
+ if(error)
1624
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1625
+
1596
1626
  } else {
1597
1627
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1598
1628
  }
1599
1629
  rb_str_set_len(result, size);
1600
- OBJ_INFECT(result, string);
1601
1630
 
1602
1631
  return result;
1603
1632
  }
@@ -1643,7 +1672,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1643
1672
  }
1644
1673
 
1645
1674
  ret = rb_str_new((char*)to, to_len - 1);
1646
- OBJ_INFECT(ret, str);
1647
1675
  PQfreemem(to);
1648
1676
  return ret;
1649
1677
  }
@@ -1673,7 +1701,6 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1673
1701
  to = PQunescapeBytea(from, &to_len);
1674
1702
 
1675
1703
  ret = rb_str_new((char*)to, to_len);
1676
- OBJ_INFECT(ret, str);
1677
1704
  PQfreemem(to);
1678
1705
  return ret;
1679
1706
  }
@@ -1684,33 +1711,27 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1684
1711
  *
1685
1712
  * Escape an arbitrary String +str+ as a literal.
1686
1713
  *
1687
- * Available since PostgreSQL-9.0
1714
+ * See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
1688
1715
  */
1689
1716
  static VALUE
1690
1717
  pgconn_escape_literal(VALUE self, VALUE string)
1691
1718
  {
1692
- PGconn *conn = pg_get_pgconn(self);
1719
+ t_pg_connection *this = pg_get_connection_safe( self );
1693
1720
  char *escaped = NULL;
1694
- VALUE error;
1695
1721
  VALUE result = Qnil;
1696
- int enc_idx = ENCODING_GET(self);
1722
+ int enc_idx = this->enc_idx;
1697
1723
 
1698
1724
  StringValueCStr(string);
1699
1725
  if( ENCODING_GET(string) != enc_idx ){
1700
1726
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1701
1727
  }
1702
1728
 
1703
- escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1729
+ escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1704
1730
  if (escaped == NULL)
1705
- {
1706
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1707
- rb_iv_set(error, "@connection", self);
1708
- rb_exc_raise(error);
1709
- return Qnil;
1710
- }
1731
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1732
+
1711
1733
  result = rb_str_new2(escaped);
1712
1734
  PQfreemem(escaped);
1713
- OBJ_INFECT(result, string);
1714
1735
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1715
1736
 
1716
1737
  return result;
@@ -1725,34 +1746,26 @@ pgconn_escape_literal(VALUE self, VALUE string)
1725
1746
  * This method does the same as #quote_ident with a String argument,
1726
1747
  * but it doesn't support an Array argument and it makes use of libpq
1727
1748
  * to process the string.
1728
- *
1729
- * Available since PostgreSQL-9.0
1730
1749
  */
1731
1750
  static VALUE
1732
1751
  pgconn_escape_identifier(VALUE self, VALUE string)
1733
1752
  {
1734
- PGconn *conn = pg_get_pgconn(self);
1753
+ t_pg_connection *this = pg_get_connection_safe( self );
1735
1754
  char *escaped = NULL;
1736
- VALUE error;
1737
1755
  VALUE result = Qnil;
1738
- int enc_idx = ENCODING_GET(self);
1756
+ int enc_idx = this->enc_idx;
1739
1757
 
1740
1758
  StringValueCStr(string);
1741
1759
  if( ENCODING_GET(string) != enc_idx ){
1742
1760
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1743
1761
  }
1744
1762
 
1745
- escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1763
+ escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1746
1764
  if (escaped == NULL)
1747
- {
1748
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1749
- rb_iv_set(error, "@connection", self);
1750
- rb_exc_raise(error);
1751
- return Qnil;
1752
- }
1765
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1766
+
1753
1767
  result = rb_str_new2(escaped);
1754
1768
  PQfreemem(escaped);
1755
- OBJ_INFECT(result, string);
1756
1769
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1757
1770
 
1758
1771
  return result;
@@ -1793,21 +1806,14 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1793
1806
  * # do something with the received row
1794
1807
  * end
1795
1808
  * end
1796
- *
1797
- * Available since PostgreSQL-9.2
1798
1809
  */
1799
1810
  static VALUE
1800
1811
  pgconn_set_single_row_mode(VALUE self)
1801
1812
  {
1802
1813
  PGconn *conn = pg_get_pgconn(self);
1803
- VALUE error;
1804
1814
 
1805
1815
  if( PQsetSingleRowMode(conn) == 0 )
1806
- {
1807
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1808
- rb_iv_set(error, "@connection", self);
1809
- rb_exc_raise(error);
1810
- }
1816
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1811
1817
 
1812
1818
  return self;
1813
1819
  }
@@ -1830,16 +1836,14 @@ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1830
1836
  static VALUE
1831
1837
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1832
1838
  {
1833
- PGconn *conn = pg_get_pgconn(self);
1834
- VALUE error;
1839
+ t_pg_connection *this = pg_get_connection_safe( self );
1835
1840
 
1836
1841
  /* If called with no or nil parameters, use PQexec for compatibility */
1837
1842
  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));
1840
- rb_iv_set(error, "@connection", self);
1841
- rb_exc_raise(error);
1842
- }
1843
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
1844
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1845
+
1846
+ pgconn_wait_for_flush( self );
1843
1847
  return Qnil;
1844
1848
  }
1845
1849
 
@@ -1869,7 +1873,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1869
1873
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1870
1874
  * { :value => <string value>, :type => 0, :format => 0 }
1871
1875
  *
1872
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1876
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1873
1877
  * inside the SQL query. The 0th element of the +params+ array is bound
1874
1878
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1875
1879
  *
@@ -1882,7 +1886,7 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1882
1886
  * The optional +result_format+ should be 0 for text results, 1
1883
1887
  * for binary.
1884
1888
  *
1885
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1889
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1886
1890
  * This will type cast the params from various Ruby types before transmission
1887
1891
  * based on the encoders defined by the type map. When a type encoder is used
1888
1892
  * the format and oid of a given bind parameter are retrieved from the encoder
@@ -1892,13 +1896,12 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1892
1896
  static VALUE
1893
1897
  pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1894
1898
  {
1895
- PGconn *conn = pg_get_pgconn(self);
1899
+ t_pg_connection *this = pg_get_connection_safe( self );
1896
1900
  int result;
1897
1901
  VALUE command, in_res_fmt;
1898
- VALUE error;
1899
1902
  int nParams;
1900
1903
  int resultFormat;
1901
- struct query_params_data paramsData = { ENCODING_GET(self) };
1904
+ struct query_params_data paramsData = { this->enc_idx };
1902
1905
 
1903
1906
  rb_scan_args(argc, argv, "22", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1904
1907
  paramsData.with_types = 1;
@@ -1907,16 +1910,15 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1907
1910
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1908
1911
  nParams = alloc_query_params( &paramsData );
1909
1912
 
1910
- result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1913
+ result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1911
1914
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1912
1915
 
1913
1916
  free_query_params( &paramsData );
1914
1917
 
1915
- if(result == 0) {
1916
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1917
- rb_iv_set(error, "@connection", self);
1918
- rb_exc_raise(error);
1919
- }
1918
+ if(result == 0)
1919
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1920
+
1921
+ pgconn_wait_for_flush( self );
1920
1922
  return Qnil;
1921
1923
  }
1922
1924
 
@@ -1937,23 +1939,22 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1937
1939
  *
1938
1940
  * For example: "SELECT $1::int"
1939
1941
  *
1940
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1942
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1941
1943
  * inside the SQL query.
1942
1944
  */
1943
1945
  static VALUE
1944
1946
  pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1945
1947
  {
1946
- PGconn *conn = pg_get_pgconn(self);
1948
+ t_pg_connection *this = pg_get_connection_safe( self );
1947
1949
  int result;
1948
1950
  VALUE name, command, in_paramtypes;
1949
1951
  VALUE param;
1950
- VALUE error;
1951
1952
  int i = 0;
1952
1953
  int nParams = 0;
1953
1954
  Oid *paramTypes = NULL;
1954
1955
  const char *name_cstr;
1955
1956
  const char *command_cstr;
1956
- int enc_idx = ENCODING_GET(self);
1957
+ int enc_idx = this->enc_idx;
1957
1958
 
1958
1959
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1959
1960
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1971,15 +1972,14 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1971
1972
  paramTypes[i] = NUM2UINT(param);
1972
1973
  }
1973
1974
  }
1974
- result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1975
+ result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1975
1976
 
1976
1977
  xfree(paramTypes);
1977
1978
 
1978
1979
  if(result == 0) {
1979
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1980
- rb_iv_set(error, "@connection", self);
1981
- rb_exc_raise(error);
1980
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1982
1981
  }
1982
+ pgconn_wait_for_flush( self );
1983
1983
  return Qnil;
1984
1984
  }
1985
1985
 
@@ -2001,14 +2001,14 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2001
2001
  * or, it may be a String. If it is a string, that is equivalent to the hash:
2002
2002
  * { :value => <string value>, :format => 0 }
2003
2003
  *
2004
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
2004
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
2005
2005
  * inside the SQL query. The 0th element of the +params+ array is bound
2006
2006
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
2007
2007
  *
2008
2008
  * The optional +result_format+ should be 0 for text results, 1
2009
2009
  * for binary.
2010
2010
  *
2011
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
2011
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
2012
2012
  * This will type cast the params from various Ruby types before transmission
2013
2013
  * based on the encoders defined by the type map. When a type encoder is used
2014
2014
  * the format and oid of a given bind parameter are retrieved from the encoder
@@ -2018,37 +2018,34 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
2018
2018
  static VALUE
2019
2019
  pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2020
2020
  {
2021
- PGconn *conn = pg_get_pgconn(self);
2021
+ t_pg_connection *this = pg_get_connection_safe( self );
2022
2022
  int result;
2023
2023
  VALUE name, in_res_fmt;
2024
- VALUE error;
2025
2024
  int nParams;
2026
2025
  int resultFormat;
2027
- struct query_params_data paramsData = { ENCODING_GET(self) };
2026
+ struct query_params_data paramsData = { this->enc_idx };
2028
2027
 
2029
2028
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
2030
2029
  paramsData.with_types = 0;
2031
2030
 
2032
2031
  if(NIL_P(paramsData.params)) {
2033
2032
  paramsData.params = rb_ary_new2(0);
2034
- resultFormat = 0;
2035
2033
  }
2036
2034
  pgconn_query_assign_typemap( self, &paramsData );
2037
2035
 
2038
2036
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
2039
2037
  nParams = alloc_query_params( &paramsData );
2040
2038
 
2041
- result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
2039
+ result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
2042
2040
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
2043
2041
  resultFormat);
2044
2042
 
2045
2043
  free_query_params( &paramsData );
2046
2044
 
2047
- if(result == 0) {
2048
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2049
- rb_iv_set(error, "@connection", self);
2050
- rb_exc_raise(error);
2051
- }
2045
+ if(result == 0)
2046
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2047
+
2048
+ pgconn_wait_for_flush( self );
2052
2049
  return Qnil;
2053
2050
  }
2054
2051
 
@@ -2062,14 +2059,12 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2062
2059
  static VALUE
2063
2060
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2064
2061
  {
2065
- VALUE error;
2066
- PGconn *conn = pg_get_pgconn(self);
2062
+ t_pg_connection *this = pg_get_connection_safe( self );
2067
2063
  /* 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));
2070
- rb_iv_set(error, "@connection", self);
2071
- rb_exc_raise(error);
2072
- }
2064
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
2065
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2066
+
2067
+ pgconn_wait_for_flush( self );
2073
2068
  return Qnil;
2074
2069
  }
2075
2070
 
@@ -2084,36 +2079,18 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2084
2079
  static VALUE
2085
2080
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2086
2081
  {
2087
- VALUE error;
2088
- PGconn *conn = pg_get_pgconn(self);
2082
+ t_pg_connection *this = pg_get_connection_safe( self );
2089
2083
  /* 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));
2092
- rb_iv_set(error, "@connection", self);
2093
- rb_exc_raise(error);
2094
- }
2084
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
2085
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2086
+
2087
+ pgconn_wait_for_flush( self );
2095
2088
  return Qnil;
2096
2089
  }
2097
2090
 
2098
2091
 
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
2092
  static VALUE
2116
- pgconn_get_result(VALUE self)
2093
+ pgconn_sync_get_result(VALUE self)
2117
2094
  {
2118
2095
  PGconn *conn = pg_get_pgconn(self);
2119
2096
  PGresult *result;
@@ -2139,17 +2116,15 @@ pgconn_get_result(VALUE self)
2139
2116
  * or *notifies* to see if the state has changed.
2140
2117
  */
2141
2118
  static VALUE
2142
- pgconn_consume_input(self)
2143
- VALUE self;
2119
+ pgconn_consume_input(VALUE self)
2144
2120
  {
2145
- VALUE error;
2146
2121
  PGconn *conn = pg_get_pgconn(self);
2147
2122
  /* returns 0 on error */
2148
2123
  if(PQconsumeInput(conn) == 0) {
2149
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2150
- rb_iv_set(error, "@connection", self);
2151
- rb_exc_raise(error);
2124
+ pgconn_close_socket_io(self);
2125
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2152
2126
  }
2127
+
2153
2128
  return Qnil;
2154
2129
  }
2155
2130
 
@@ -2158,37 +2133,18 @@ pgconn_consume_input(self)
2158
2133
  * conn.is_busy() -> Boolean
2159
2134
  *
2160
2135
  * Returns +true+ if a command is busy, that is, if
2161
- * PQgetResult would block. Otherwise returns +false+.
2136
+ * #get_result would block. Otherwise returns +false+.
2162
2137
  */
2163
2138
  static VALUE
2164
- pgconn_is_busy(self)
2165
- VALUE self;
2139
+ pgconn_is_busy(VALUE self)
2166
2140
  {
2167
2141
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2168
2142
  }
2169
2143
 
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
2144
  static VALUE
2187
- pgconn_setnonblocking(self, state)
2188
- VALUE self, state;
2145
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2189
2146
  {
2190
2147
  int arg;
2191
- VALUE error;
2192
2148
  PGconn *conn = pg_get_pgconn(self);
2193
2149
  if(state == Qtrue)
2194
2150
  arg = 1;
@@ -2197,67 +2153,32 @@ pgconn_setnonblocking(self, state)
2197
2153
  else
2198
2154
  rb_raise(rb_eArgError, "Boolean value expected");
2199
2155
 
2200
- if(PQsetnonblocking(conn, arg) == -1) {
2201
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2202
- rb_iv_set(error, "@connection", self);
2203
- rb_exc_raise(error);
2204
- }
2156
+ if(PQsetnonblocking(conn, arg) == -1)
2157
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2158
+
2205
2159
  return Qnil;
2206
2160
  }
2207
2161
 
2208
2162
 
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
2163
  static VALUE
2217
- pgconn_isnonblocking(self)
2218
- VALUE self;
2164
+ pgconn_sync_isnonblocking(VALUE self)
2219
2165
  {
2220
2166
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2221
2167
  }
2222
2168
 
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
2169
  static VALUE
2234
- pgconn_flush(self)
2235
- VALUE self;
2170
+ pgconn_sync_flush(VALUE self)
2236
2171
  {
2237
2172
  PGconn *conn = pg_get_pgconn(self);
2238
- int ret;
2239
- VALUE error;
2240
- ret = PQflush(conn);
2241
- if(ret == -1) {
2242
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2243
- rb_iv_set(error, "@connection", self);
2244
- rb_exc_raise(error);
2245
- }
2173
+ int ret = PQflush(conn);
2174
+ if(ret == -1)
2175
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2176
+
2246
2177
  return (ret) ? Qfalse : Qtrue;
2247
2178
  }
2248
2179
 
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
2180
  static VALUE
2260
- pgconn_cancel(VALUE self)
2181
+ pgconn_sync_cancel(VALUE self)
2261
2182
  {
2262
2183
  char errbuf[256];
2263
2184
  PGcancel *cancel;
@@ -2266,9 +2187,9 @@ pgconn_cancel(VALUE self)
2266
2187
 
2267
2188
  cancel = PQgetCancel(pg_get_pgconn(self));
2268
2189
  if(cancel == NULL)
2269
- rb_raise(rb_ePGerror,"Invalid connection!");
2190
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2270
2191
 
2271
- ret = gvl_PQcancel(cancel, errbuf, 256);
2192
+ ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2272
2193
  if(ret == 1)
2273
2194
  retval = Qnil;
2274
2195
  else
@@ -2289,7 +2210,7 @@ pgconn_cancel(VALUE self)
2289
2210
  static VALUE
2290
2211
  pgconn_notifies(VALUE self)
2291
2212
  {
2292
- PGconn* conn = pg_get_pgconn(self);
2213
+ t_pg_connection *this = pg_get_connection_safe( self );
2293
2214
  PGnotify *notification;
2294
2215
  VALUE hash;
2295
2216
  VALUE sym_relname, sym_be_pid, sym_extra;
@@ -2299,17 +2220,17 @@ pgconn_notifies(VALUE self)
2299
2220
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2300
2221
  sym_extra = ID2SYM(rb_intern("extra"));
2301
2222
 
2302
- notification = gvl_PQnotifies(conn);
2223
+ notification = gvl_PQnotifies(this->pgconn);
2303
2224
  if (notification == NULL) {
2304
2225
  return Qnil;
2305
2226
  }
2306
2227
 
2307
2228
  hash = rb_hash_new();
2308
- relname = rb_tainted_str_new2(notification->relname);
2229
+ relname = rb_str_new2(notification->relname);
2309
2230
  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) );
2231
+ extra = rb_str_new2(notification->extra);
2232
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2233
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2313
2234
 
2314
2235
  rb_hash_aset(hash, sym_relname, relname);
2315
2236
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -2319,55 +2240,63 @@ pgconn_notifies(VALUE self)
2319
2240
  return hash;
2320
2241
  }
2321
2242
 
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().
2243
+ #if defined(_WIN32)
2244
+
2245
+ /* We use a specialized implementation of rb_io_wait() on Windows.
2246
+ * This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
2327
2247
  */
2328
2248
 
2249
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2250
+ #include <ruby/fiber/scheduler.h>
2251
+ #endif
2252
+
2253
+ typedef enum {
2254
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2255
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2256
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2257
+ } pg_rb_io_event_t;
2258
+
2329
2259
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2330
2260
 
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;
2261
+ static VALUE
2262
+ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
2263
+ rb_io_t *fptr;
2264
+ struct timeval ptimeout;
2265
+
2336
2266
  struct timeval aborttime={0,0}, currtime, waittime;
2337
2267
  DWORD timeout_milisec = INFINITE;
2338
- DWORD wait_ret;
2339
- WSAEVENT hEvent;
2340
-
2341
- if ( sd < 0 )
2342
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2268
+ HANDLE hEvent = WSACreateEvent();
2343
2269
 
2344
- hEvent = WSACreateEvent();
2270
+ long rb_events = NUM2UINT(events);
2271
+ long w32_events = 0;
2272
+ DWORD wait_ret;
2345
2273
 
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
- }
2274
+ GetOpenFile((io), fptr);
2275
+ if( !NIL_P(timeout) ){
2276
+ ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
2277
+ ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
2351
2278
 
2352
- if ( ptimeout ) {
2353
2279
  gettimeofday(&currtime, NULL);
2354
- timeradd(&currtime, ptimeout, &aborttime);
2280
+ timeradd(&currtime, &ptimeout, &aborttime);
2355
2281
  }
2356
2282
 
2357
- while ( !(retval=is_readable(conn)) ) {
2358
- if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2283
+ if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2284
+ if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
2285
+ if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
2286
+
2287
+ for(;;) {
2288
+ if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
2359
2289
  WSACloseEvent( hEvent );
2360
2290
  rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2361
2291
  }
2362
2292
 
2363
- if ( ptimeout ) {
2293
+ if ( !NIL_P(timeout) ) {
2364
2294
  gettimeofday(&currtime, NULL);
2365
2295
  timersub(&aborttime, &currtime, &waittime);
2366
2296
  timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
2367
2297
  }
2368
2298
 
2369
- /* Is the given timeout valid? */
2370
- if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2299
+ if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2371
2300
  /* Wait for the socket to become readable before checking again */
2372
2301
  wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2373
2302
  } else {
@@ -2376,9 +2305,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2376
2305
 
2377
2306
  if ( wait_ret == WAIT_TIMEOUT ) {
2378
2307
  WSACloseEvent( hEvent );
2379
- return NULL;
2308
+ return UINT2NUM(0);
2380
2309
  } else if ( wait_ret == WAIT_OBJECT_0 ) {
2310
+ WSACloseEvent( hEvent );
2381
2311
  /* The event we were waiting for. */
2312
+ return UINT2NUM(rb_events);
2382
2313
  } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2383
2314
  /* This indicates interruption from timer thread, GC, exception
2384
2315
  * from other threads etc... */
@@ -2390,36 +2321,66 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2390
2321
  WSACloseEvent( hEvent );
2391
2322
  rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
2392
2323
  }
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
2324
  }
2325
+ }
2400
2326
 
2401
- WSACloseEvent( hEvent );
2402
- return retval;
2327
+ static VALUE
2328
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2329
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2330
+ /* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
2331
+ * Fortunatelly ruby-3.1 offers a C-API for it.
2332
+ */
2333
+ VALUE scheduler = rb_fiber_scheduler_current();
2334
+
2335
+ if (!NIL_P(scheduler)) {
2336
+ return rb_io_wait(io, events, timeout);
2337
+ }
2338
+ #endif
2339
+ return pg_rb_thread_io_wait(io, events, timeout);
2403
2340
  }
2404
2341
 
2342
+ #elif defined(HAVE_RB_IO_WAIT)
2343
+
2344
+ /* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
2345
+ #define pg_rb_io_wait rb_io_wait
2346
+ #define PG_RUBY_IO_READABLE RUBY_IO_READABLE
2347
+ #define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
2348
+ #define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
2349
+
2405
2350
  #else
2351
+ /* For compat with ruby < 3.0 */
2352
+
2353
+ typedef enum {
2354
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2355
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2356
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2357
+ } pg_rb_io_event_t;
2358
+
2359
+ static VALUE
2360
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2361
+ rb_io_t *fptr;
2362
+ struct timeval waittime;
2363
+ int res;
2364
+
2365
+ GetOpenFile((io), fptr);
2366
+ if( !NIL_P(timeout) ){
2367
+ waittime.tv_sec = (time_t)(NUM2DBL(timeout));
2368
+ waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
2369
+ }
2370
+ res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
2406
2371
 
2407
- /* non Win32 */
2372
+ return UINT2NUM(res);
2373
+ }
2374
+ #endif
2408
2375
 
2409
2376
  static void *
2410
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2377
+ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2411
2378
  {
2412
- int sd = PQsocket( conn );
2413
- int ret;
2379
+ VALUE ret;
2414
2380
  void *retval;
2415
2381
  struct timeval aborttime={0,0}, currtime, waittime;
2416
-
2417
- if ( sd < 0 )
2418
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2419
-
2420
- /* Check for connection errors (PQisBusy is true on connection errors) */
2421
- if ( PQconsumeInput(conn) == 0 )
2422
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2382
+ VALUE wait_timeout = Qnil;
2383
+ PGconn *conn = pg_get_pgconn(self);
2423
2384
 
2424
2385
  if ( ptimeout ) {
2425
2386
  gettimeofday(&currtime, NULL);
@@ -2430,36 +2391,79 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2430
2391
  if ( ptimeout ) {
2431
2392
  gettimeofday(&currtime, NULL);
2432
2393
  timersub(&aborttime, &currtime, &waittime);
2394
+ wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
2433
2395
  }
2434
2396
 
2435
2397
  /* Is the given timeout valid? */
2436
2398
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2399
+ VALUE socket_io;
2400
+
2401
+ /* before we wait for data, make sure everything has been sent */
2402
+ pgconn_async_flush(self);
2403
+ if ((retval=is_readable(conn)))
2404
+ return retval;
2405
+
2406
+ socket_io = pgconn_socket_io(self);
2437
2407
  /* Wait for the socket to become readable before checking again */
2438
- ret = rb_wait_for_single_fd( sd, RB_WAITFD_IN, ptimeout ? &waittime : NULL );
2408
+ ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2439
2409
  } else {
2440
- ret = 0;
2441
- }
2442
-
2443
- if ( ret < 0 ){
2444
- rb_sys_fail( "rb_wait_for_single_fd()" );
2410
+ ret = Qfalse;
2445
2411
  }
2446
2412
 
2447
2413
  /* Return false if the select() timed out */
2448
- if ( ret == 0 ){
2414
+ if ( ret == Qfalse ){
2449
2415
  return NULL;
2450
2416
  }
2451
2417
 
2452
2418
  /* Check for connection errors (PQisBusy is true on connection errors) */
2453
2419
  if ( PQconsumeInput(conn) == 0 ){
2454
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2420
+ pgconn_close_socket_io(self);
2421
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2455
2422
  }
2456
2423
  }
2457
2424
 
2458
2425
  return retval;
2459
2426
  }
2460
2427
 
2428
+ /*
2429
+ * call-seq:
2430
+ * conn.flush() -> Boolean
2431
+ *
2432
+ * Attempts to flush any queued output data to the server.
2433
+ * Returns +true+ if data is successfully flushed, +false+
2434
+ * if not. It can only return +false+ if connection is
2435
+ * in nonblocking mode.
2436
+ * Raises PG::Error if some other failure occurred.
2437
+ */
2438
+ static VALUE
2439
+ pgconn_async_flush(VALUE self)
2440
+ {
2441
+ while( pgconn_sync_flush(self) == Qfalse ){
2442
+ /* wait for the socket to become read- or write-ready */
2443
+ int events;
2444
+ VALUE socket_io = pgconn_socket_io(self);
2445
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2461
2446
 
2462
- #endif
2447
+ if (events & PG_RUBY_IO_READABLE)
2448
+ pgconn_consume_input(self);
2449
+ }
2450
+ return Qtrue;
2451
+ }
2452
+
2453
+ static VALUE
2454
+ pgconn_wait_for_flush( VALUE self ){
2455
+ if( !pg_get_connection_safe(self)->flush_data )
2456
+ return Qnil;
2457
+
2458
+ return pgconn_async_flush(self);
2459
+ }
2460
+
2461
+ static VALUE
2462
+ pgconn_flush_data_set( VALUE self, VALUE enabled ){
2463
+ t_pg_connection *conn = pg_get_connection(self);
2464
+ conn->flush_data = RTEST(enabled);
2465
+ return enabled;
2466
+ }
2463
2467
 
2464
2468
  static void *
2465
2469
  notify_readable(PGconn *conn)
@@ -2482,7 +2486,7 @@ notify_readable(PGconn *conn)
2482
2486
  static VALUE
2483
2487
  pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2484
2488
  {
2485
- PGconn *conn = pg_get_pgconn( self );
2489
+ t_pg_connection *this = pg_get_connection_safe( self );
2486
2490
  PGnotify *pnotification;
2487
2491
  struct timeval timeout;
2488
2492
  struct timeval *ptimeout = NULL;
@@ -2498,17 +2502,17 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2498
2502
  ptimeout = &timeout;
2499
2503
  }
2500
2504
 
2501
- pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
2505
+ pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
2502
2506
 
2503
2507
  /* Return nil if the select timed out */
2504
2508
  if ( !pnotification ) return Qnil;
2505
2509
 
2506
- relname = rb_tainted_str_new2( pnotification->relname );
2507
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2510
+ relname = rb_str_new2( pnotification->relname );
2511
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2508
2512
  be_pid = INT2NUM( pnotification->be_pid );
2509
2513
  if ( *pnotification->extra ) {
2510
- extra = rb_tainted_str_new2( pnotification->extra );
2511
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2514
+ extra = rb_str_new2( pnotification->extra );
2515
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2512
2516
  }
2513
2517
  PQfreemem( pnotification );
2514
2518
 
@@ -2519,28 +2523,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2519
2523
  }
2520
2524
 
2521
2525
 
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
2526
  static VALUE
2543
- pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2527
+ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2544
2528
  {
2545
2529
  int ret;
2546
2530
  int len;
@@ -2557,18 +2541,16 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2557
2541
  if( NIL_P(this->encoder_for_put_copy_data) ){
2558
2542
  buffer = value;
2559
2543
  } else {
2560
- p_coder = DATA_PTR( this->encoder_for_put_copy_data );
2544
+ p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
2561
2545
  }
2562
- } else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
2563
- Data_Get_Struct( encoder, t_pg_coder, p_coder );
2564
2546
  } else {
2565
- rb_raise( rb_eTypeError, "wrong encoder type %s (expected some kind of PG::Coder)",
2566
- rb_obj_classname( encoder ) );
2547
+ /* Check argument type and use argument encoder */
2548
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
2567
2549
  }
2568
2550
 
2569
2551
  if( p_coder ){
2570
2552
  t_pg_coder_enc_func enc_func;
2571
- int enc_idx = ENCODING_GET(self);
2553
+ int enc_idx = this->enc_idx;
2572
2554
 
2573
2555
  enc_func = pg_coder_enc_func( p_coder );
2574
2556
  len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
@@ -2586,78 +2568,39 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2586
2568
  Check_Type(buffer, T_STRING);
2587
2569
 
2588
2570
  ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2589
- if(ret == -1) {
2590
- VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2591
- rb_iv_set(error, "@connection", self);
2592
- rb_exc_raise(error);
2593
- }
2571
+ if(ret == -1)
2572
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2573
+
2594
2574
  RB_GC_GUARD(intermediate);
2595
2575
  RB_GC_GUARD(buffer);
2596
2576
 
2597
2577
  return (ret) ? Qtrue : Qfalse;
2598
2578
  }
2599
2579
 
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
2580
  static VALUE
2615
- pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2581
+ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2616
2582
  {
2617
2583
  VALUE str;
2618
- VALUE error;
2619
2584
  int ret;
2620
2585
  const char *error_message = NULL;
2621
- PGconn *conn = pg_get_pgconn(self);
2586
+ t_pg_connection *this = pg_get_connection_safe( self );
2622
2587
 
2623
2588
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2624
2589
  error_message = NULL;
2625
2590
  else
2626
- error_message = pg_cstr_enc(str, ENCODING_GET(self));
2591
+ error_message = pg_cstr_enc(str, this->enc_idx);
2592
+
2593
+ ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2594
+ if(ret == -1)
2595
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2627
2596
 
2628
- ret = gvl_PQputCopyEnd(conn, error_message);
2629
- if(ret == -1) {
2630
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2631
- rb_iv_set(error, "@connection", self);
2632
- rb_exc_raise(error);
2633
- }
2634
2597
  return (ret) ? Qtrue : Qfalse;
2635
2598
  }
2636
2599
 
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
2600
  static VALUE
2657
- pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2601
+ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2658
2602
  {
2659
2603
  VALUE async_in;
2660
- VALUE error;
2661
2604
  VALUE result;
2662
2605
  int ret;
2663
2606
  char *buffer;
@@ -2669,20 +2612,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2669
2612
 
2670
2613
  if( NIL_P(decoder) ){
2671
2614
  if( !NIL_P(this->decoder_for_get_copy_data) ){
2672
- p_coder = DATA_PTR( this->decoder_for_get_copy_data );
2615
+ p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
2673
2616
  }
2674
- } else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
2675
- Data_Get_Struct( decoder, t_pg_coder, p_coder );
2676
2617
  } else {
2677
- rb_raise( rb_eTypeError, "wrong decoder type %s (expected some kind of PG::Coder)",
2678
- rb_obj_classname( decoder ) );
2618
+ /* Check argument type and use argument decoder */
2619
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
2679
2620
  }
2680
2621
 
2681
2622
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2682
- if(ret == -2) { /* error */
2683
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2684
- rb_iv_set(error, "@connection", self);
2685
- rb_exc_raise(error);
2623
+ if(ret == -2){ /* error */
2624
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2686
2625
  }
2687
2626
  if(ret == -1) { /* No data left */
2688
2627
  return Qnil;
@@ -2693,9 +2632,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2693
2632
 
2694
2633
  if( p_coder ){
2695
2634
  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) );
2635
+ result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2697
2636
  } else {
2698
- result = rb_tainted_str_new(buffer, ret);
2637
+ result = rb_str_new(buffer, ret);
2699
2638
  }
2700
2639
 
2701
2640
  PQfreemem(buffer);
@@ -2708,9 +2647,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2708
2647
  *
2709
2648
  * Sets connection's verbosity to _verbosity_ and returns
2710
2649
  * the previous setting. Available settings are:
2650
+ *
2711
2651
  * * PQERRORS_TERSE
2712
2652
  * * PQERRORS_DEFAULT
2713
2653
  * * PQERRORS_VERBOSE
2654
+ * * PQERRORS_SQLSTATE
2655
+ *
2656
+ * Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2657
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
2658
+ *
2659
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
2714
2660
  */
2715
2661
  static VALUE
2716
2662
  pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
@@ -2720,6 +2666,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2720
2666
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2721
2667
  }
2722
2668
 
2669
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2670
+ /*
2671
+ * call-seq:
2672
+ * conn.set_error_context_visibility( context_visibility ) -> Integer
2673
+ *
2674
+ * Sets connection's context display mode to _context_visibility_ and returns
2675
+ * the previous setting. Available settings are:
2676
+ * * PQSHOW_CONTEXT_NEVER
2677
+ * * PQSHOW_CONTEXT_ERRORS
2678
+ * * PQSHOW_CONTEXT_ALWAYS
2679
+ *
2680
+ * This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
2681
+ * The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
2682
+ * In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
2683
+ *
2684
+ * Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2685
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
2686
+ *
2687
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2688
+ *
2689
+ * Available since PostgreSQL-9.6
2690
+ */
2691
+ static VALUE
2692
+ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2693
+ {
2694
+ PGconn *conn = pg_get_pgconn(self);
2695
+ PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2696
+ return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2697
+ }
2698
+ #endif
2699
+
2723
2700
  /*
2724
2701
  * call-seq:
2725
2702
  * conn.trace( stream ) -> nil
@@ -2738,7 +2715,7 @@ pgconn_trace(VALUE self, VALUE stream)
2738
2715
  VALUE new_file;
2739
2716
  t_pg_connection *this = pg_get_connection_safe( self );
2740
2717
 
2741
- if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2718
+ if(!rb_respond_to(stream,rb_intern("fileno")))
2742
2719
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2743
2720
 
2744
2721
  fileno = rb_funcall(stream, rb_intern("fileno"), 0);
@@ -2871,8 +2848,8 @@ notice_processor_proxy(void *arg, const char *message)
2871
2848
  t_pg_connection *this = pg_get_connection( self );
2872
2849
 
2873
2850
  if (this->notice_receiver != Qnil) {
2874
- VALUE message_str = rb_tainted_str_new2(message);
2875
- PG_ENCODING_SET_NOCHECK( message_str, ENCODING_GET(self) );
2851
+ VALUE message_str = rb_str_new2(message);
2852
+ PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2876
2853
  rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2877
2854
  }
2878
2855
  return;
@@ -2882,7 +2859,7 @@ notice_processor_proxy(void *arg, const char *message)
2882
2859
  * call-seq:
2883
2860
  * conn.set_notice_processor {|message| ... } -> Proc
2884
2861
  *
2885
- * See #set_notice_receiver for the desription of what this and the
2862
+ * See #set_notice_receiver for the description of what this and the
2886
2863
  * notice_processor methods do.
2887
2864
  *
2888
2865
  * This function takes a new block to act as the notice processor and returns
@@ -2930,74 +2907,33 @@ static VALUE
2930
2907
  pgconn_get_client_encoding(VALUE self)
2931
2908
  {
2932
2909
  char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2933
- return rb_tainted_str_new2(encoding);
2910
+ return rb_str_new2(encoding);
2934
2911
  }
2935
2912
 
2936
2913
 
2937
2914
  /*
2938
2915
  * call-seq:
2939
- * conn.set_client_encoding( encoding )
2916
+ * conn.sync_set_client_encoding( encoding )
2940
2917
  *
2941
- * Sets the client encoding to the _encoding_ String.
2918
+ * This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
2919
+ * See #async_exec for the differences between the two API variants.
2920
+ * 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
2921
  */
2943
2922
  static VALUE
2944
- pgconn_set_client_encoding(VALUE self, VALUE str)
2923
+ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2945
2924
  {
2946
2925
  PGconn *conn = pg_get_pgconn( self );
2947
2926
 
2948
2927
  Check_Type(str, T_STRING);
2949
2928
 
2950
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2951
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2952
- }
2929
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2930
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2931
+
2953
2932
  pgconn_set_internal_encoding_index( self );
2954
2933
 
2955
2934
  return Qnil;
2956
2935
  }
2957
2936
 
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
2937
 
3002
2938
  /*
3003
2939
  * call-seq:
@@ -3042,14 +2978,12 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3042
2978
  int enc_idx;
3043
2979
 
3044
2980
  if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3045
- enc_idx = ENCODING_GET( self );
2981
+ enc_idx = pg_get_connection(self)->enc_idx;
3046
2982
  }else{
3047
2983
  enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3048
2984
  }
3049
2985
  pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3050
2986
 
3051
- OBJ_INFECT(ret, str_or_array);
3052
-
3053
2987
  return ret;
3054
2988
  }
3055
2989
 
@@ -3074,10 +3008,8 @@ get_result_readable(PGconn *conn)
3074
3008
  * If +true+ is returned, +conn.is_busy+ will return +false+
3075
3009
  * and +conn.get_result+ will not block.
3076
3010
  */
3077
- static VALUE
3011
+ VALUE
3078
3012
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
3079
- PGconn *conn = pg_get_pgconn( self );
3080
-
3081
3013
  struct timeval timeout;
3082
3014
  struct timeval *ptimeout = NULL;
3083
3015
  VALUE timeout_in;
@@ -3091,7 +3023,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3091
3023
  ptimeout = &timeout;
3092
3024
  }
3093
3025
 
3094
- ret = wait_socket_readable( conn, ptimeout, get_result_readable);
3026
+ ret = wait_socket_readable( self, ptimeout, get_result_readable);
3095
3027
 
3096
3028
  if( !ret )
3097
3029
  return Qfalse;
@@ -3100,6 +3032,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3100
3032
  }
3101
3033
 
3102
3034
 
3035
+ /*
3036
+ * call-seq:
3037
+ * conn.sync_get_last_result( ) -> PG::Result
3038
+ *
3039
+ * This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
3040
+ * See #async_exec for the differences between the two API variants.
3041
+ * 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.
3042
+ */
3043
+ static VALUE
3044
+ pgconn_sync_get_last_result(VALUE self)
3045
+ {
3046
+ PGconn *conn = pg_get_pgconn(self);
3047
+ VALUE rb_pgresult = Qnil;
3048
+ PGresult *cur, *prev;
3049
+
3050
+
3051
+ cur = prev = NULL;
3052
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
3053
+ int status;
3054
+
3055
+ if (prev) PQclear(prev);
3056
+ prev = cur;
3057
+
3058
+ status = PQresultStatus(cur);
3059
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3060
+ break;
3061
+ }
3062
+
3063
+ if (prev) {
3064
+ rb_pgresult = pg_new_result( prev, self );
3065
+ pg_result_check(rb_pgresult);
3066
+ }
3067
+
3068
+ return rb_pgresult;
3069
+ }
3070
+
3103
3071
  /*
3104
3072
  * call-seq:
3105
3073
  * conn.get_last_result( ) -> PG::Result
@@ -3110,27 +3078,36 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3110
3078
  * returns the last non-NULL result, or +nil+ if no
3111
3079
  * results are available.
3112
3080
  *
3081
+ * If the last result contains a bad result_status, an
3082
+ * appropriate exception is raised.
3083
+ *
3113
3084
  * This function is similar to #get_result
3114
3085
  * except that it is designed to get one and only
3115
- * one result.
3086
+ * one result and that it checks the result state.
3116
3087
  */
3117
3088
  static VALUE
3118
- pgconn_get_last_result(VALUE self)
3089
+ pgconn_async_get_last_result(VALUE self)
3119
3090
  {
3120
3091
  PGconn *conn = pg_get_pgconn(self);
3121
3092
  VALUE rb_pgresult = Qnil;
3122
3093
  PGresult *cur, *prev;
3123
3094
 
3124
-
3125
- cur = prev = NULL;
3126
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3095
+ cur = prev = NULL;
3096
+ for(;;) {
3127
3097
  int status;
3128
3098
 
3099
+ /* wait for input (without blocking) before reading each result */
3100
+ wait_socket_readable(self, NULL, get_result_readable);
3101
+
3102
+ cur = gvl_PQgetResult(conn);
3103
+ if (cur == NULL)
3104
+ break;
3105
+
3129
3106
  if (prev) PQclear(prev);
3130
3107
  prev = cur;
3131
3108
 
3132
3109
  status = PQresultStatus(cur);
3133
- if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
3110
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3134
3111
  break;
3135
3112
  }
3136
3113
 
@@ -3154,39 +3131,89 @@ static VALUE
3154
3131
  pgconn_discard_results(VALUE self)
3155
3132
  {
3156
3133
  PGconn *conn = pg_get_pgconn(self);
3134
+ VALUE socket_io;
3157
3135
 
3158
- PGresult *cur;
3159
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3160
- int status = PQresultStatus(cur);
3161
- PQclear(cur);
3162
- if (status == PGRES_COPY_IN){
3136
+ if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3137
+ return Qnil;
3138
+ }
3139
+
3140
+ socket_io = pgconn_socket_io(self);
3141
+
3142
+ for(;;) {
3143
+ PGresult *cur;
3144
+ int status;
3145
+
3146
+ /* pgconn_block() raises an exception in case of errors.
3147
+ * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3148
+ */
3149
+ while( gvl_PQisBusy(conn) ){
3150
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3151
+ if ( PQconsumeInput(conn) == 0 ) {
3152
+ pgconn_close_socket_io(self);
3153
+ return Qfalse;
3154
+ }
3155
+ }
3156
+
3157
+ cur = gvl_PQgetResult(conn);
3158
+ if( cur == NULL) break;
3159
+
3160
+ status = PQresultStatus(cur);
3161
+ PQclear(cur);
3162
+ if (status == PGRES_COPY_IN){
3163
3163
  gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
3164
3164
  }
3165
3165
  if (status == PGRES_COPY_OUT){
3166
- char *buffer = NULL;
3167
- while( gvl_PQgetCopyData(conn, &buffer, 0) > 0)
3168
- PQfreemem(buffer);
3166
+ for(;;) {
3167
+ char *buffer = NULL;
3168
+ int st = gvl_PQgetCopyData(conn, &buffer, 1);
3169
+ if( st == 0 ) {
3170
+ /* would block -> wait for readable data */
3171
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3172
+ if ( PQconsumeInput(conn) == 0 ) {
3173
+ pgconn_close_socket_io(self);
3174
+ return Qfalse;
3175
+ }
3176
+ } else if( st > 0 ) {
3177
+ /* some data retrieved -> discard it */
3178
+ PQfreemem(buffer);
3179
+ } else {
3180
+ /* no more data */
3181
+ break;
3182
+ }
3183
+ }
3169
3184
  }
3170
3185
  }
3171
3186
 
3172
- return Qnil;
3187
+ return Qtrue;
3173
3188
  }
3174
3189
 
3175
3190
  /*
3176
3191
  * call-seq:
3177
- * conn.async_exec(sql) -> PG::Result
3178
- * conn.async_exec(sql) {|pg_result| block }
3192
+ * conn.exec(sql) -> PG::Result
3193
+ * conn.exec(sql) {|pg_result| block }
3179
3194
  *
3180
- * This function has the same behavior as #sync_exec,
3181
- * but is implemented using the asynchronous command
3182
- * processing API of libpq.
3195
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
3196
+ * On success, it returns a PG::Result instance with all result rows and columns.
3197
+ * On failure, it raises a PG::Error.
3183
3198
  *
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:
3199
+ * For backward compatibility, if you pass more than one parameter to this method,
3200
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
3201
+ * argument placeholders are used.
3186
3202
  *
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
3203
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3204
+ * and the PG::Result object will automatically be cleared when the block terminates.
3205
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3206
+ *
3207
+ * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3208
+ * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3209
+ * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3210
+ * Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
3211
+ * Both methods ensure that other threads can process while waiting for the server to
3212
+ * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3213
+ * This is most notably visible by a delayed reaction to Control+C.
3214
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3215
+ *
3216
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
3190
3217
  */
3191
3218
  static VALUE
3192
3219
  pgconn_async_exec(int argc, VALUE *argv, VALUE self)
@@ -3195,8 +3222,7 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3195
3222
 
3196
3223
  pgconn_discard_results( self );
3197
3224
  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 );
3225
+ rb_pgresult = pgconn_async_get_last_result( self );
3200
3226
 
3201
3227
  if ( rb_block_given_p() ) {
3202
3228
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3207,11 +3233,53 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3207
3233
 
3208
3234
  /*
3209
3235
  * 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 }
3236
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3237
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3212
3238
  *
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.
3239
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
3240
+ * for parameters.
3241
+ *
3242
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
3243
+ *
3244
+ * +params+ is an array of the bind parameters for the SQL query.
3245
+ * Each element of the +params+ array may be either:
3246
+ * a hash of the form:
3247
+ * {:value => String (value of bind parameter)
3248
+ * :type => Integer (oid of type of bind parameter)
3249
+ * :format => Integer (0 for text, 1 for binary)
3250
+ * }
3251
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3252
+ * { :value => <string value>, :type => 0, :format => 0 }
3253
+ *
3254
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3255
+ * inside the SQL query. The 0th element of the +params+ array is bound
3256
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3257
+ *
3258
+ * If the types are not specified, they will be inferred by PostgreSQL.
3259
+ * Instead of specifying type oids, it's recommended to simply add
3260
+ * explicit casts in the query to ensure that the right type is used.
3261
+ *
3262
+ * For example: "SELECT $1::int"
3263
+ *
3264
+ * The optional +result_format+ should be 0 for text results, 1
3265
+ * for binary.
3266
+ *
3267
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3268
+ * This will type cast the params from various Ruby types before transmission
3269
+ * based on the encoders defined by the type map. When a type encoder is used
3270
+ * the format and oid of a given bind parameter are retrieved from the encoder
3271
+ * instead out of the hash form described above.
3272
+ *
3273
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3274
+ * and the PG::Result object will automatically be cleared when the block terminates.
3275
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3276
+ *
3277
+ * 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.
3278
+ * Unlike #exec, #exec_params allows at most one SQL command in the given string.
3279
+ * (There can be semicolons in it, but not more than one nonempty command.)
3280
+ * This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
3281
+ *
3282
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
3215
3283
  */
3216
3284
  static VALUE
3217
3285
  pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
@@ -3226,8 +3294,7 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3226
3294
  } else {
3227
3295
  pgconn_send_query_params( argc, argv, self );
3228
3296
  }
3229
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3230
- rb_pgresult = pgconn_get_last_result( self );
3297
+ rb_pgresult = pgconn_async_get_last_result( self );
3231
3298
 
3232
3299
  if ( rb_block_given_p() ) {
3233
3300
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3238,10 +3305,25 @@ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3238
3305
 
3239
3306
  /*
3240
3307
  * call-seq:
3241
- * conn.async_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3308
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3242
3309
  *
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.
3310
+ * Prepares statement _sql_ with name _name_ to be executed later.
3311
+ * Returns a PG::Result instance on success.
3312
+ * On failure, it raises a PG::Error.
3313
+ *
3314
+ * +param_types+ is an optional parameter to specify the Oids of the
3315
+ * types of the parameters.
3316
+ *
3317
+ * If the types are not specified, they will be inferred by PostgreSQL.
3318
+ * Instead of specifying type oids, it's recommended to simply add
3319
+ * explicit casts in the query to ensure that the right type is used.
3320
+ *
3321
+ * For example: "SELECT $1::int"
3322
+ *
3323
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3324
+ * inside the SQL query.
3325
+ *
3326
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
3245
3327
  */
3246
3328
  static VALUE
3247
3329
  pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
@@ -3250,8 +3332,7 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3250
3332
 
3251
3333
  pgconn_discard_results( self );
3252
3334
  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 );
3335
+ rb_pgresult = pgconn_async_get_last_result( self );
3255
3336
 
3256
3337
  if ( rb_block_given_p() ) {
3257
3338
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3262,11 +3343,40 @@ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3262
3343
 
3263
3344
  /*
3264
3345
  * 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 }
3346
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3347
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3267
3348
  *
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.
3349
+ * Execute prepared named statement specified by _statement_name_.
3350
+ * Returns a PG::Result instance on success.
3351
+ * On failure, it raises a PG::Error.
3352
+ *
3353
+ * +params+ is an array of the optional bind parameters for the
3354
+ * SQL query. Each element of the +params+ array may be either:
3355
+ * a hash of the form:
3356
+ * {:value => String (value of bind parameter)
3357
+ * :format => Integer (0 for text, 1 for binary)
3358
+ * }
3359
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3360
+ * { :value => <string value>, :format => 0 }
3361
+ *
3362
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3363
+ * inside the SQL query. The 0th element of the +params+ array is bound
3364
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3365
+ *
3366
+ * The optional +result_format+ should be 0 for text results, 1
3367
+ * for binary.
3368
+ *
3369
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3370
+ * This will type cast the params from various Ruby types before transmission
3371
+ * based on the encoders defined by the type map. When a type encoder is used
3372
+ * the format and oid of a given bind parameter are retrieved from the encoder
3373
+ * instead out of the hash form described above.
3374
+ *
3375
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3376
+ * and the PG::Result object will automatically be cleared when the block terminates.
3377
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
3378
+ *
3379
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
3270
3380
  */
3271
3381
  static VALUE
3272
3382
  pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
@@ -3275,8 +3385,7 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3275
3385
 
3276
3386
  pgconn_discard_results( self );
3277
3387
  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 );
3388
+ rb_pgresult = pgconn_async_get_last_result( self );
3280
3389
 
3281
3390
  if ( rb_block_given_p() ) {
3282
3391
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3287,10 +3396,11 @@ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3287
3396
 
3288
3397
  /*
3289
3398
  * call-seq:
3290
- * conn.async_describe_portal( portal_name ) -> PG::Result
3399
+ * conn.describe_portal( portal_name ) -> PG::Result
3291
3400
  *
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.
3401
+ * Retrieve information about the portal _portal_name_.
3402
+ *
3403
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
3294
3404
  */
3295
3405
  static VALUE
3296
3406
  pgconn_async_describe_portal(VALUE self, VALUE portal)
@@ -3299,8 +3409,7 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3299
3409
 
3300
3410
  pgconn_discard_results( self );
3301
3411
  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 );
3412
+ rb_pgresult = pgconn_async_get_last_result( self );
3304
3413
 
3305
3414
  if ( rb_block_given_p() ) {
3306
3415
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3311,10 +3420,11 @@ pgconn_async_describe_portal(VALUE self, VALUE portal)
3311
3420
 
3312
3421
  /*
3313
3422
  * call-seq:
3314
- * conn.async_describe_prepared( statement_name ) -> PG::Result
3423
+ * conn.describe_prepared( statement_name ) -> PG::Result
3315
3424
  *
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.
3425
+ * Retrieve information about the prepared statement _statement_name_.
3426
+ *
3427
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
3318
3428
  */
3319
3429
  static VALUE
3320
3430
  pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
@@ -3323,8 +3433,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3323
3433
 
3324
3434
  pgconn_discard_results( self );
3325
3435
  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 );
3436
+ rb_pgresult = pgconn_async_get_last_result( self );
3328
3437
 
3329
3438
  if ( rb_block_given_p() ) {
3330
3439
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3338,7 +3447,7 @@ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3338
3447
  * call-seq:
3339
3448
  * conn.ssl_in_use? -> Boolean
3340
3449
  *
3341
- * Returns +true+ if the connection uses SSL, +false+ if not.
3450
+ * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3342
3451
  *
3343
3452
  * Available since PostgreSQL-9.5
3344
3453
  */
@@ -3372,7 +3481,7 @@ pgconn_ssl_in_use(VALUE self)
3372
3481
  * 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
3482
  *
3374
3483
  *
3375
- * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3484
+ * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3376
3485
  *
3377
3486
  * Available since PostgreSQL-9.5
3378
3487
  */
@@ -3412,6 +3521,122 @@ pgconn_ssl_attribute_names(VALUE self)
3412
3521
  #endif
3413
3522
 
3414
3523
 
3524
+ #ifdef HAVE_PQENTERPIPELINEMODE
3525
+ /*
3526
+ * call-seq:
3527
+ * conn.pipeline_status -> Integer
3528
+ *
3529
+ * Returns the current pipeline mode status of the libpq connection.
3530
+ *
3531
+ * PQpipelineStatus can return one of the following values:
3532
+ *
3533
+ * * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
3534
+ * * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
3535
+ * * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
3536
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
3537
+ *
3538
+ * Available since PostgreSQL-14
3539
+ */
3540
+ static VALUE
3541
+ pgconn_pipeline_status(VALUE self)
3542
+ {
3543
+ int res = PQpipelineStatus(pg_get_pgconn(self));
3544
+ return INT2FIX(res);
3545
+ }
3546
+
3547
+
3548
+ /*
3549
+ * call-seq:
3550
+ * conn.enter_pipeline_mode -> nil
3551
+ *
3552
+ * Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
3553
+ *
3554
+ * 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.
3555
+ * This function does not actually send anything to the server, it just changes the libpq connection state.
3556
+ *
3557
+ * Available since PostgreSQL-14
3558
+ */
3559
+ static VALUE
3560
+ pgconn_enter_pipeline_mode(VALUE self)
3561
+ {
3562
+ PGconn *conn = pg_get_pgconn(self);
3563
+ int res = PQenterPipelineMode(conn);
3564
+ if( res != 1 )
3565
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3566
+
3567
+ return Qnil;
3568
+ }
3569
+
3570
+ /*
3571
+ * call-seq:
3572
+ * conn.exit_pipeline_mode -> nil
3573
+ *
3574
+ * Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
3575
+ *
3576
+ * Takes no action if not in pipeline mode.
3577
+ * 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.
3578
+ *
3579
+ * Available since PostgreSQL-14
3580
+ */
3581
+ static VALUE
3582
+ pgconn_exit_pipeline_mode(VALUE self)
3583
+ {
3584
+ PGconn *conn = pg_get_pgconn(self);
3585
+ int res = PQexitPipelineMode(conn);
3586
+ if( res != 1 )
3587
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3588
+
3589
+ return Qnil;
3590
+ }
3591
+
3592
+
3593
+ /*
3594
+ * call-seq:
3595
+ * conn.pipeline_sync -> nil
3596
+ *
3597
+ * Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
3598
+ * This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
3599
+ *
3600
+ * Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
3601
+ *
3602
+ * Available since PostgreSQL-14
3603
+ */
3604
+ static VALUE
3605
+ pgconn_pipeline_sync(VALUE self)
3606
+ {
3607
+ PGconn *conn = pg_get_pgconn(self);
3608
+ int res = PQpipelineSync(conn);
3609
+ if( res != 1 )
3610
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3611
+
3612
+ return Qnil;
3613
+ }
3614
+
3615
+ /*
3616
+ * call-seq:
3617
+ * conn.pipeline_sync -> nil
3618
+ *
3619
+ * Sends a request for the server to flush its output buffer.
3620
+ *
3621
+ * 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.
3622
+ * This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
3623
+ * Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
3624
+ *
3625
+ * Available since PostgreSQL-14
3626
+ */
3627
+ static VALUE
3628
+ pgconn_send_flush_request(VALUE self)
3629
+ {
3630
+ PGconn *conn = pg_get_pgconn(self);
3631
+ int res = PQsendFlushRequest(conn);
3632
+ if( res != 1 )
3633
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3634
+
3635
+ return Qnil;
3636
+ }
3637
+
3638
+ #endif
3639
+
3415
3640
  /**************************************************************************
3416
3641
  * LARGE OBJECT SUPPORT
3417
3642
  **************************************************************************/
@@ -3438,7 +3663,7 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3438
3663
 
3439
3664
  lo_oid = lo_creat(conn, mode);
3440
3665
  if (lo_oid == 0)
3441
- rb_raise(rb_ePGerror, "lo_creat failed");
3666
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3442
3667
 
3443
3668
  return UINT2NUM(lo_oid);
3444
3669
  }
@@ -3459,7 +3684,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3459
3684
 
3460
3685
  ret = lo_create(conn, lo_oid);
3461
3686
  if (ret == InvalidOid)
3462
- rb_raise(rb_ePGerror, "lo_create failed");
3687
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3463
3688
 
3464
3689
  return UINT2NUM(ret);
3465
3690
  }
@@ -3483,7 +3708,7 @@ pgconn_loimport(VALUE self, VALUE filename)
3483
3708
 
3484
3709
  lo_oid = lo_import(conn, StringValueCStr(filename));
3485
3710
  if (lo_oid == 0) {
3486
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3711
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3487
3712
  }
3488
3713
  return UINT2NUM(lo_oid);
3489
3714
  }
@@ -3504,7 +3729,7 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3504
3729
  oid = NUM2UINT(lo_oid);
3505
3730
 
3506
3731
  if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3507
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3732
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3508
3733
  }
3509
3734
  return Qnil;
3510
3735
  }
@@ -3535,7 +3760,7 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3535
3760
  mode = NUM2INT(nmode);
3536
3761
 
3537
3762
  if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3538
- rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3763
+ pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3539
3764
  }
3540
3765
  return INT2FIX(fd);
3541
3766
  }
@@ -3557,11 +3782,11 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3557
3782
  Check_Type(buffer, T_STRING);
3558
3783
 
3559
3784
  if( RSTRING_LEN(buffer) < 0) {
3560
- rb_raise(rb_ePGerror, "write buffer zero string");
3785
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3561
3786
  }
3562
3787
  if((n = lo_write(conn, fd, StringValuePtr(buffer),
3563
3788
  RSTRING_LEN(buffer))) < 0) {
3564
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3789
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3565
3790
  }
3566
3791
 
3567
3792
  return INT2FIX(n);
@@ -3584,23 +3809,19 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3584
3809
  VALUE str;
3585
3810
  char *buffer;
3586
3811
 
3587
- buffer = ALLOC_N(char, len);
3588
- if(buffer == NULL)
3589
- rb_raise(rb_eNoMemError, "ALLOC failed!");
3590
-
3591
- if (len < 0){
3592
- rb_raise(rb_ePGerror,"nagative length %d given", len);
3593
- }
3812
+ if (len < 0)
3813
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3594
3814
 
3815
+ buffer = ALLOC_N(char, len);
3595
3816
  if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3596
- rb_raise(rb_ePGerror, "lo_read failed");
3817
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3597
3818
 
3598
3819
  if(ret == 0) {
3599
3820
  xfree(buffer);
3600
3821
  return Qnil;
3601
3822
  }
3602
3823
 
3603
- str = rb_tainted_str_new(buffer, ret);
3824
+ str = rb_str_new(buffer, ret);
3604
3825
  xfree(buffer);
3605
3826
 
3606
3827
  return str;
@@ -3623,7 +3844,7 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3623
3844
  int ret;
3624
3845
 
3625
3846
  if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3626
- rb_raise(rb_ePGerror, "lo_lseek failed");
3847
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3627
3848
  }
3628
3849
 
3629
3850
  return INT2FIX(ret);
@@ -3643,7 +3864,7 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3643
3864
  int lo_desc = NUM2INT(in_lo_desc);
3644
3865
 
3645
3866
  if((position = lo_tell(conn, lo_desc)) < 0)
3646
- rb_raise(rb_ePGerror,"lo_tell failed");
3867
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3647
3868
 
3648
3869
  return INT2FIX(position);
3649
3870
  }
@@ -3662,7 +3883,7 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3662
3883
  size_t len = NUM2INT(in_len);
3663
3884
 
3664
3885
  if(lo_truncate(conn,lo_desc,len) < 0)
3665
- rb_raise(rb_ePGerror,"lo_truncate failed");
3886
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3666
3887
 
3667
3888
  return Qnil;
3668
3889
  }
@@ -3680,7 +3901,7 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3680
3901
  int lo_desc = NUM2INT(in_lo_desc);
3681
3902
 
3682
3903
  if(lo_close(conn,lo_desc) < 0)
3683
- rb_raise(rb_ePGerror,"lo_close failed");
3904
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3684
3905
 
3685
3906
  return Qnil;
3686
3907
  }
@@ -3698,18 +3919,21 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3698
3919
  Oid oid = NUM2UINT(in_oid);
3699
3920
 
3700
3921
  if(lo_unlink(conn,oid) < 0)
3701
- rb_raise(rb_ePGerror,"lo_unlink failed");
3922
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3702
3923
 
3703
3924
  return Qnil;
3704
3925
  }
3705
3926
 
3706
3927
 
3707
- void
3928
+ static void
3708
3929
  pgconn_set_internal_encoding_index( VALUE self )
3709
3930
  {
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));
3931
+ int enc_idx;
3932
+ t_pg_connection *this = pg_get_connection_safe( self );
3933
+ rb_encoding *enc = pg_conn_enc_get( this->pgconn );
3934
+ enc_idx = rb_enc_to_index(enc);
3935
+ if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
3936
+ this->enc_idx = enc_idx;
3713
3937
  }
3714
3938
 
3715
3939
  /*
@@ -3752,13 +3976,12 @@ static VALUE pgconn_external_encoding(VALUE self);
3752
3976
  static VALUE
3753
3977
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3754
3978
  {
3755
- VALUE enc_inspect;
3756
3979
  if (NIL_P(enc)) {
3757
- pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3980
+ pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3758
3981
  return enc;
3759
3982
  }
3760
3983
  else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
3761
- pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3984
+ pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3762
3985
  return enc;
3763
3986
  }
3764
3987
  else {
@@ -3773,11 +3996,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3773
3996
  pgconn_set_internal_encoding_index( self );
3774
3997
  return enc;
3775
3998
  }
3776
-
3777
- enc_inspect = rb_inspect(enc);
3778
- rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
3779
-
3780
- return Qnil;
3781
3999
  }
3782
4000
 
3783
4001
 
@@ -3796,42 +4014,55 @@ pgconn_external_encoding(VALUE self)
3796
4014
  rb_encoding *enc = NULL;
3797
4015
  const char *pg_encname = NULL;
3798
4016
 
3799
- /* Use cached value if found */
3800
- if ( RTEST(this->external_encoding) ) return this->external_encoding;
3801
-
3802
4017
  pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
3803
4018
  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;
4019
+ return rb_enc_from_encoding( enc );
3807
4020
  }
3808
4021
 
4022
+ /*
4023
+ * call-seq:
4024
+ * conn.set_client_encoding( encoding )
4025
+ *
4026
+ * Sets the client encoding to the _encoding_ String.
4027
+ */
4028
+ static VALUE
4029
+ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4030
+ {
4031
+ VALUE query_format, query;
4032
+
4033
+ Check_Type(encname, T_STRING);
4034
+ query_format = rb_str_new_cstr("set client_encoding to '%s'");
4035
+ query = rb_funcall(query_format, rb_intern("%"), 1, encname);
4036
+
4037
+ pgconn_async_exec(1, &query, self);
4038
+ pgconn_set_internal_encoding_index( self );
4039
+
4040
+ return Qnil;
4041
+ }
3809
4042
 
3810
4043
  static VALUE
3811
4044
  pgconn_set_client_encoding_async1( VALUE args )
3812
4045
  {
3813
4046
  VALUE self = ((VALUE*)args)[0];
3814
4047
  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);
4048
+ pgconn_async_set_client_encoding(self, encname);
3819
4049
  return 0;
3820
4050
  }
3821
4051
 
3822
4052
 
3823
4053
  static VALUE
3824
- pgconn_set_client_encoding_async2( VALUE arg )
4054
+ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3825
4055
  {
3826
4056
  UNUSED(arg);
4057
+ UNUSED(ex);
3827
4058
  return 1;
3828
4059
  }
3829
4060
 
3830
4061
 
3831
4062
  static VALUE
3832
- pgconn_set_client_encoding_async( VALUE self, const char *encname )
4063
+ pgconn_set_client_encoding_async( VALUE self, VALUE encname )
3833
4064
  {
3834
- VALUE args[] = { self, rb_str_new_cstr(encname) };
4065
+ VALUE args[] = { self, encname };
3835
4066
  return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3836
4067
  }
3837
4068
 
@@ -3853,10 +4084,9 @@ pgconn_set_default_encoding( VALUE self )
3853
4084
 
3854
4085
  if (( enc = rb_default_internal_encoding() )) {
3855
4086
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3856
- if ( pgconn_set_client_encoding_async(self, encname) != 0 )
4087
+ if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
3857
4088
  rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
3858
4089
  encname, PQerrorMessage(conn) );
3859
- pgconn_set_internal_encoding_index( self );
3860
4090
  return rb_enc_from_encoding( enc );
3861
4091
  } else {
3862
4092
  pgconn_set_internal_encoding_index( self );
@@ -3878,12 +4108,12 @@ static VALUE
3878
4108
  pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
3879
4109
  {
3880
4110
  t_pg_connection *this = pg_get_connection( self );
4111
+ t_typemap *tm;
4112
+ UNUSED(tm);
4113
+
4114
+ /* Check type of method param */
4115
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3881
4116
 
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
4117
  this->type_map_for_queries = typemap;
3888
4118
 
3889
4119
  return typemap;
@@ -3918,12 +4148,10 @@ static VALUE
3918
4148
  pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
3919
4149
  {
3920
4150
  t_pg_connection *this = pg_get_connection( self );
4151
+ t_typemap *tm;
4152
+ UNUSED(tm);
3921
4153
 
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);
4154
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3927
4155
  this->type_map_for_results = typemap;
3928
4156
 
3929
4157
  return typemap;
@@ -3958,20 +4186,19 @@ pgconn_type_map_for_results_get(VALUE self)
3958
4186
  *
3959
4187
  */
3960
4188
  static VALUE
3961
- pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
4189
+ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
3962
4190
  {
3963
4191
  t_pg_connection *this = pg_get_connection( self );
3964
4192
 
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);
4193
+ if( encoder != Qnil ){
4194
+ t_pg_coder *co;
4195
+ UNUSED(co);
4196
+ /* Check argument type */
4197
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
3971
4198
  }
3972
- this->encoder_for_put_copy_data = typemap;
4199
+ this->encoder_for_put_copy_data = encoder;
3973
4200
 
3974
- return typemap;
4201
+ return encoder;
3975
4202
  }
3976
4203
 
3977
4204
  /*
@@ -4007,20 +4234,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
4007
4234
  *
4008
4235
  */
4009
4236
  static VALUE
4010
- pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE typemap)
4237
+ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4011
4238
  {
4012
4239
  t_pg_connection *this = pg_get_connection( self );
4013
4240
 
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);
4241
+ if( decoder != Qnil ){
4242
+ t_pg_coder *co;
4243
+ UNUSED(co);
4244
+ /* Check argument type */
4245
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
4020
4246
  }
4021
- this->decoder_for_get_copy_data = typemap;
4247
+ this->decoder_for_get_copy_data = decoder;
4022
4248
 
4023
- return typemap;
4249
+ return decoder;
4024
4250
  }
4025
4251
 
4026
4252
  /*
@@ -4045,16 +4271,54 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
4045
4271
 
4046
4272
  /*
4047
4273
  * call-seq:
4048
- * res.guess_result_memsize = enabled
4274
+ * conn.field_name_type = Symbol
4275
+ *
4276
+ * Set default type of field names of results retrieved by this connection.
4277
+ * It can be set to one of:
4278
+ * * +:string+ to use String based field names
4279
+ * * +:symbol+ to use Symbol based field names
4280
+ *
4281
+ * The default is +:string+ .
4282
+ *
4283
+ * Settings the type of field names affects only future results.
4284
+ *
4285
+ * See further description at PG::Result#field_name_type=
4286
+ *
4287
+ */
4288
+ static VALUE
4289
+ pgconn_field_name_type_set(VALUE self, VALUE sym)
4290
+ {
4291
+ t_pg_connection *this = pg_get_connection( self );
4292
+
4293
+ this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4294
+ if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4295
+ else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4296
+ else if ( sym == sym_string );
4297
+ else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4298
+
4299
+ return sym;
4300
+ }
4301
+
4302
+ /*
4303
+ * call-seq:
4304
+ * conn.field_name_type -> Symbol
4049
4305
  *
4050
- * This method is for testing only and will probably be removed in the future.
4306
+ * Get type of field names.
4307
+ *
4308
+ * See description at #field_name_type=
4051
4309
  */
4052
4310
  static VALUE
4053
- pgconn_guess_result_memsize_set(VALUE self, VALUE enable)
4311
+ pgconn_field_name_type_get(VALUE self)
4054
4312
  {
4055
4313
  t_pg_connection *this = pg_get_connection( self );
4056
- this->guess_result_memsize = RTEST(enable);
4057
- return enable;
4314
+
4315
+ if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4316
+ return sym_symbol;
4317
+ } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4318
+ return sym_static_symbol;
4319
+ } else {
4320
+ return sym_string;
4321
+ }
4058
4322
  }
4059
4323
 
4060
4324
 
@@ -4065,20 +4329,22 @@ void
4065
4329
  init_pg_connection()
4066
4330
  {
4067
4331
  s_id_encode = rb_intern("encode");
4332
+ s_id_autoclose_set = rb_intern("autoclose=");
4068
4333
  sym_type = ID2SYM(rb_intern("type"));
4069
4334
  sym_format = ID2SYM(rb_intern("format"));
4070
4335
  sym_value = ID2SYM(rb_intern("value"));
4336
+ sym_string = ID2SYM(rb_intern("string"));
4337
+ sym_symbol = ID2SYM(rb_intern("symbol"));
4338
+ sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
4071
4339
 
4072
4340
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4341
+ /* Help rdoc to known the Constants module */
4342
+ /* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
4073
4343
  rb_include_module(rb_cPGconn, rb_mPGconstants);
4074
4344
 
4075
4345
  /****** PG::Connection CLASS METHODS ******/
4076
4346
  rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
4077
4347
 
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
4348
  rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4083
4349
  SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
4084
4350
  rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
@@ -4087,14 +4353,15 @@ init_pg_connection()
4087
4353
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4088
4354
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4089
4355
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4090
- rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
4356
+ rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
4357
+ rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4358
+ rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4091
4359
 
4092
4360
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
4093
- rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
4094
4361
  rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
4095
4362
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
4096
4363
  rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
4097
- rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
4364
+ rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
4098
4365
  rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
4099
4366
  rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
4100
4367
  rb_define_alias(rb_cPGconn, "close", "finish");
@@ -4104,11 +4371,12 @@ init_pg_connection()
4104
4371
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4105
4372
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4106
4373
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4374
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
4375
+ rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
4376
+ #endif
4107
4377
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4108
4378
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4109
- #ifdef HAVE_PQCONNINFO
4110
4379
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
4111
- #endif
4112
4380
  rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
4113
4381
  rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
4114
4382
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
@@ -4119,17 +4387,34 @@ init_pg_connection()
4119
4387
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
4120
4388
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
4121
4389
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4390
+ rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
4122
4391
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
4123
4392
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
4124
4393
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
4125
4394
 
4126
4395
  /****** 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);
4396
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
4397
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
4398
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
4399
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4400
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4401
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4402
+
4403
+ rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4404
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
4405
+ rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
4406
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4407
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4408
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4409
+
4410
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
4411
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4412
+ rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
4413
+ rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
4414
+ rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4415
+ rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4416
+ rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4417
+
4133
4418
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
4134
4419
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
4135
4420
  rb_define_alias(rb_cPGconn, "escape", "escape_string");
@@ -4142,42 +4427,38 @@ init_pg_connection()
4142
4427
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
4143
4428
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
4144
4429
  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
4430
  rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
4149
- rb_define_method(rb_cPGconn, "async_prepare", pgconn_async_prepare, -1);
4150
4431
  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
4432
  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
4433
  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);
4434
+ rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
4157
4435
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4158
4436
  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);
4437
+ rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
4438
+ rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
4439
+ rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
4440
+ rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
4441
+ rb_define_alias(rb_cPGconn, "async_flush", "flush");
4163
4442
  rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4164
4443
 
4165
4444
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4166
- rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
4445
+ rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4167
4446
 
4168
4447
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4169
4448
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
4170
4449
 
4171
4450
  /****** 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);
4451
+ rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
4452
+ rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
4453
+ rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
4175
4454
 
4176
4455
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4177
4456
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4457
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4458
+ rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4459
+ #endif
4178
4460
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
4179
4461
  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
4462
 
4182
4463
  /****** PG::Connection INSTANCE METHODS: Notice Processing ******/
4183
4464
  rb_define_method(rb_cPGconn, "set_notice_receiver", pgconn_set_notice_receiver, 0);
@@ -4185,16 +4466,20 @@ init_pg_connection()
4185
4466
 
4186
4467
  /****** PG::Connection INSTANCE METHODS: Other ******/
4187
4468
  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);
4469
+ rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
4470
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
4471
+ rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
4189
4472
  rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
4190
- rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
4191
4473
  rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
4474
+ rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
4192
4475
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
4193
4476
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
4194
4477
  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);
4478
+ rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4479
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4480
+ rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4196
4481
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
4197
- rb_define_method(rb_cPGconn, "encrypt_password", pgconn_encrypt_password, -1);
4482
+ rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4198
4483
  #endif
4199
4484
 
4200
4485
  #ifdef HAVE_PQSSLATTRIBUTE
@@ -4203,6 +4488,14 @@ init_pg_connection()
4203
4488
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4204
4489
  #endif
4205
4490
 
4491
+ #ifdef HAVE_PQENTERPIPELINEMODE
4492
+ rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4493
+ rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4494
+ rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4495
+ rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
4496
+ rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4497
+ #endif
4498
+
4206
4499
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
4207
4500
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
4208
4501
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
@@ -4244,5 +4537,7 @@ init_pg_connection()
4244
4537
  rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
4245
4538
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
4246
4539
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
4247
- }
4248
4540
 
4541
+ rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
4542
+ rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
4543
+ }