pg 0.21.0 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +42 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +117 -0
  6. data/.github/workflows/source-gem.yml +137 -0
  7. data/.gitignore +22 -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.md +876 -0
  16. data/Manifest.txt +8 -4
  17. data/README-Windows.rdoc +4 -4
  18. data/README.ja.md +276 -0
  19. data/README.md +286 -0
  20. data/Rakefile +38 -139
  21. data/Rakefile.cross +70 -74
  22. data/certs/ged.pem +24 -0
  23. data/certs/larskanis-2022.pem +26 -0
  24. data/certs/larskanis-2023.pem +24 -0
  25. data/ext/errorcodes.def +88 -0
  26. data/ext/errorcodes.rb +1 -1
  27. data/ext/errorcodes.txt +24 -2
  28. data/ext/extconf.rb +111 -54
  29. data/ext/gvl_wrappers.c +8 -0
  30. data/ext/gvl_wrappers.h +40 -33
  31. data/ext/pg.c +224 -199
  32. data/ext/pg.h +93 -96
  33. data/ext/pg_binary_decoder.c +162 -16
  34. data/ext/pg_binary_encoder.c +238 -13
  35. data/ext/pg_coder.c +159 -35
  36. data/ext/pg_connection.c +1585 -1046
  37. data/ext/pg_copy_coder.c +364 -38
  38. data/ext/pg_errors.c +1 -1
  39. data/ext/pg_record_coder.c +522 -0
  40. data/ext/pg_result.c +708 -219
  41. data/ext/pg_text_decoder.c +627 -43
  42. data/ext/pg_text_encoder.c +206 -62
  43. data/ext/pg_tuple.c +572 -0
  44. data/ext/pg_type_map.c +45 -11
  45. data/ext/pg_type_map_all_strings.c +21 -7
  46. data/ext/pg_type_map_by_class.c +59 -27
  47. data/ext/pg_type_map_by_column.c +80 -37
  48. data/ext/pg_type_map_by_mri_type.c +49 -20
  49. data/ext/pg_type_map_by_oid.c +62 -29
  50. data/ext/pg_type_map_in_ruby.c +56 -22
  51. data/ext/{util.c → pg_util.c} +12 -12
  52. data/ext/{util.h → pg_util.h} +2 -2
  53. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  54. data/lib/pg/basic_type_map_for_queries.rb +198 -0
  55. data/lib/pg/basic_type_map_for_results.rb +104 -0
  56. data/lib/pg/basic_type_registry.rb +299 -0
  57. data/lib/pg/binary_decoder/date.rb +9 -0
  58. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  59. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  60. data/lib/pg/coder.rb +36 -13
  61. data/lib/pg/connection.rb +755 -71
  62. data/lib/pg/exceptions.rb +16 -2
  63. data/lib/pg/result.rb +14 -2
  64. data/lib/pg/text_decoder/date.rb +18 -0
  65. data/lib/pg/text_decoder/inet.rb +9 -0
  66. data/lib/pg/text_decoder/json.rb +14 -0
  67. data/lib/pg/text_decoder/numeric.rb +9 -0
  68. data/lib/pg/text_decoder/timestamp.rb +30 -0
  69. data/lib/pg/text_encoder/date.rb +12 -0
  70. data/lib/pg/text_encoder/inet.rb +28 -0
  71. data/lib/pg/text_encoder/json.rb +14 -0
  72. data/lib/pg/text_encoder/numeric.rb +9 -0
  73. data/lib/pg/text_encoder/timestamp.rb +24 -0
  74. data/lib/pg/tuple.rb +30 -0
  75. data/lib/pg/type_map_by_column.rb +3 -2
  76. data/lib/pg/version.rb +4 -0
  77. data/lib/pg.rb +96 -43
  78. data/misc/openssl-pg-segfault.rb +31 -0
  79. data/misc/postgres/History.txt +9 -0
  80. data/misc/postgres/Manifest.txt +5 -0
  81. data/misc/postgres/README.txt +21 -0
  82. data/misc/postgres/Rakefile +21 -0
  83. data/misc/postgres/lib/postgres.rb +16 -0
  84. data/misc/ruby-pg/History.txt +9 -0
  85. data/misc/ruby-pg/Manifest.txt +5 -0
  86. data/misc/ruby-pg/README.txt +21 -0
  87. data/misc/ruby-pg/Rakefile +21 -0
  88. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  89. data/pg.gemspec +34 -0
  90. data/rakelib/task_extension.rb +46 -0
  91. data/sample/array_insert.rb +20 -0
  92. data/sample/async_api.rb +102 -0
  93. data/sample/async_copyto.rb +39 -0
  94. data/sample/async_mixed.rb +56 -0
  95. data/sample/check_conn.rb +21 -0
  96. data/sample/copydata.rb +71 -0
  97. data/sample/copyfrom.rb +81 -0
  98. data/sample/copyto.rb +19 -0
  99. data/sample/cursor.rb +21 -0
  100. data/sample/disk_usage_report.rb +177 -0
  101. data/sample/issue-119.rb +94 -0
  102. data/sample/losample.rb +69 -0
  103. data/sample/minimal-testcase.rb +17 -0
  104. data/sample/notify_wait.rb +72 -0
  105. data/sample/pg_statistics.rb +285 -0
  106. data/sample/replication_monitor.rb +222 -0
  107. data/sample/test_binary_values.rb +33 -0
  108. data/sample/wal_shipper.rb +434 -0
  109. data/sample/warehouse_partitions.rb +311 -0
  110. data/translation/.po4a-version +7 -0
  111. data/translation/po/all.pot +910 -0
  112. data/translation/po/ja.po +1047 -0
  113. data/translation/po4a.cfg +12 -0
  114. data.tar.gz.sig +0 -0
  115. metadata +154 -217
  116. metadata.gz.sig +0 -0
  117. data/ChangeLog +0 -6595
  118. data/History.rdoc +0 -394
  119. data/README.ja.rdoc +0 -14
  120. data/README.rdoc +0 -168
  121. data/lib/pg/basic_type_mapping.rb +0 -426
  122. data/lib/pg/constants.rb +0 -11
  123. data/lib/pg/deprecated_constants.rb +0 -21
  124. data/lib/pg/text_decoder.rb +0 -51
  125. data/lib/pg/text_encoder.rb +0 -35
  126. data/spec/data/expected_trace.out +0 -26
  127. data/spec/data/random_binary_data +0 -0
  128. data/spec/helpers.rb +0 -352
  129. data/spec/pg/basic_type_mapping_spec.rb +0 -305
  130. data/spec/pg/connection_spec.rb +0 -1676
  131. data/spec/pg/result_spec.rb +0 -456
  132. data/spec/pg/type_map_by_class_spec.rb +0 -138
  133. data/spec/pg/type_map_by_column_spec.rb +0 -222
  134. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  135. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  136. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  137. data/spec/pg/type_map_spec.rb +0 -22
  138. data/spec/pg/type_spec.rb +0 -777
  139. 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 2e17f315848e 2017/01/14 20:05:06 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -12,30 +12,41 @@
12
12
 
13
13
  VALUE rb_cPGconn;
14
14
  static ID s_id_encode;
15
+ static ID s_id_autoclose_set;
15
16
  static VALUE sym_type, sym_format, sym_value;
16
-
17
- static PQnoticeReceiver default_notice_receiver = NULL;
18
- static PQnoticeProcessor default_notice_processor = NULL;
17
+ static VALUE sym_symbol, sym_string, sym_static_symbol;
19
18
 
20
19
  static VALUE pgconn_finish( VALUE );
21
- #ifdef M17N_SUPPORTED
22
20
  static VALUE pgconn_set_default_encoding( VALUE self );
23
- void pgconn_set_internal_encoding_index( VALUE );
24
- #endif
25
-
26
- #ifndef HAVE_RB_THREAD_FD_SELECT
27
- #define rb_fdset_t fd_set
28
- #define rb_fd_init(f)
29
- #define rb_fd_zero(f) FD_ZERO(f)
30
- #define rb_fd_set(n, f) FD_SET(n, f)
31
- #define rb_fd_term(f)
32
- #define rb_thread_fd_select rb_thread_select
33
- #endif
21
+ static VALUE pgconn_wait_for_flush( VALUE self );
22
+ static void pgconn_set_internal_encoding_index( VALUE );
23
+ static const rb_data_type_t pg_connection_type;
24
+ static VALUE pgconn_async_flush(VALUE self);
34
25
 
35
26
  /*
36
27
  * Global functions
37
28
  */
38
29
 
30
+ /*
31
+ * Convenience function to raise connection errors
32
+ */
33
+ #ifdef __GNUC__
34
+ __attribute__((format(printf, 3, 4)))
35
+ #endif
36
+ static void
37
+ pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
38
+ {
39
+ VALUE msg, error;
40
+ va_list ap;
41
+
42
+ va_start(ap, format);
43
+ msg = rb_vsprintf(format, ap);
44
+ va_end(ap);
45
+ error = rb_exc_new_str(klass, msg);
46
+ rb_iv_set(error, "@connection", self);
47
+ rb_exc_raise(error);
48
+ }
49
+
39
50
  /*
40
51
  * Fetch the PG::Connection object data pointer.
41
52
  */
@@ -43,7 +54,7 @@ t_pg_connection *
43
54
  pg_get_connection( VALUE self )
44
55
  {
45
56
  t_pg_connection *this;
46
- Data_Get_Struct( self, t_pg_connection, this);
57
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
47
58
 
48
59
  return this;
49
60
  }
@@ -56,10 +67,10 @@ static t_pg_connection *
56
67
  pg_get_connection_safe( VALUE self )
57
68
  {
58
69
  t_pg_connection *this;
59
- Data_Get_Struct( self, t_pg_connection, this);
70
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
60
71
 
61
72
  if ( !this->pgconn )
62
- rb_raise( rb_eConnectionBad, "connection is closed" );
73
+ pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
63
74
 
64
75
  return this;
65
76
  }
@@ -75,10 +86,11 @@ PGconn *
75
86
  pg_get_pgconn( VALUE self )
76
87
  {
77
88
  t_pg_connection *this;
78
- Data_Get_Struct( self, t_pg_connection, this);
89
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
79
90
 
80
- if ( !this->pgconn )
81
- rb_raise( rb_eConnectionBad, "connection is closed" );
91
+ if ( !this->pgconn ){
92
+ pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
93
+ }
82
94
 
83
95
  return this->pgconn;
84
96
  }
@@ -95,16 +107,14 @@ pgconn_close_socket_io( VALUE self )
95
107
  VALUE socket_io = this->socket_io;
96
108
 
97
109
  if ( RTEST(socket_io) ) {
98
- #if defined(_WIN32) && defined(HAVE_RB_W32_WRAP_IO_HANDLE)
99
- int ruby_sd = NUM2INT(rb_funcall( socket_io, rb_intern("fileno"), 0 ));
100
- if( rb_w32_unwrap_io_handle(ruby_sd) ){
101
- rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
102
- }
110
+ #if defined(_WIN32)
111
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) )
112
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
103
113
  #endif
104
114
  rb_funcall( socket_io, rb_intern("close"), 0 );
105
115
  }
106
116
 
107
- this->socket_io = Qnil;
117
+ RB_OBJ_WRITE(self, &this->socket_io, Qnil);
108
118
  }
109
119
 
110
120
 
@@ -156,17 +166,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
156
166
  * GC Mark function
157
167
  */
158
168
  static void
159
- pgconn_gc_mark( t_pg_connection *this )
169
+ pgconn_gc_mark( void *_this )
170
+ {
171
+ t_pg_connection *this = (t_pg_connection *)_this;
172
+ rb_gc_mark_movable( this->socket_io );
173
+ rb_gc_mark_movable( this->notice_receiver );
174
+ rb_gc_mark_movable( this->notice_processor );
175
+ rb_gc_mark_movable( this->type_map_for_queries );
176
+ rb_gc_mark_movable( this->type_map_for_results );
177
+ rb_gc_mark_movable( this->trace_stream );
178
+ rb_gc_mark_movable( this->encoder_for_put_copy_data );
179
+ rb_gc_mark_movable( this->decoder_for_get_copy_data );
180
+ }
181
+
182
+ static void
183
+ pgconn_gc_compact( void *_this )
160
184
  {
161
- rb_gc_mark( this->socket_io );
162
- rb_gc_mark( this->notice_receiver );
163
- rb_gc_mark( this->notice_processor );
164
- rb_gc_mark( this->type_map_for_queries );
165
- rb_gc_mark( this->type_map_for_results );
166
- rb_gc_mark( this->trace_stream );
167
- rb_gc_mark( this->external_encoding );
168
- rb_gc_mark( this->encoder_for_put_copy_data );
169
- rb_gc_mark( this->decoder_for_get_copy_data );
185
+ t_pg_connection *this = (t_pg_connection *)_this;
186
+ pg_gc_location( this->socket_io );
187
+ pg_gc_location( this->notice_receiver );
188
+ pg_gc_location( this->notice_processor );
189
+ pg_gc_location( this->type_map_for_queries );
190
+ pg_gc_location( this->type_map_for_results );
191
+ pg_gc_location( this->trace_stream );
192
+ pg_gc_location( this->encoder_for_put_copy_data );
193
+ pg_gc_location( this->decoder_for_get_copy_data );
170
194
  }
171
195
 
172
196
 
@@ -174,14 +198,45 @@ pgconn_gc_mark( t_pg_connection *this )
174
198
  * GC Free function
175
199
  */
176
200
  static void
177
- pgconn_gc_free( t_pg_connection *this )
201
+ pgconn_gc_free( void *_this )
178
202
  {
203
+ t_pg_connection *this = (t_pg_connection *)_this;
204
+ #if defined(_WIN32)
205
+ if ( RTEST(this->socket_io) ) {
206
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
207
+ rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
208
+ }
209
+ }
210
+ #endif
179
211
  if (this->pgconn != NULL)
180
212
  PQfinish( this->pgconn );
181
213
 
182
214
  xfree(this);
183
215
  }
184
216
 
217
+ /*
218
+ * Object Size function
219
+ */
220
+ static size_t
221
+ pgconn_memsize( const void *_this )
222
+ {
223
+ const t_pg_connection *this = (const t_pg_connection *)_this;
224
+ return sizeof(*this);
225
+ }
226
+
227
+ static const rb_data_type_t pg_connection_type = {
228
+ "PG::Connection",
229
+ {
230
+ pgconn_gc_mark,
231
+ pgconn_gc_free,
232
+ pgconn_memsize,
233
+ pg_compact_callback(pgconn_gc_compact),
234
+ },
235
+ 0,
236
+ 0,
237
+ RUBY_TYPED_WB_PROTECTED,
238
+ };
239
+
185
240
 
186
241
  /**************************************************************************
187
242
  * Class Methods
@@ -197,103 +252,40 @@ static VALUE
197
252
  pgconn_s_allocate( VALUE klass )
198
253
  {
199
254
  t_pg_connection *this;
200
- VALUE self = Data_Make_Struct( klass, t_pg_connection, pgconn_gc_mark, pgconn_gc_free, this );
255
+ VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
201
256
 
202
257
  this->pgconn = NULL;
203
- this->socket_io = Qnil;
204
- this->notice_receiver = Qnil;
205
- this->notice_processor = Qnil;
206
- this->type_map_for_queries = pg_typemap_all_strings;
207
- this->type_map_for_results = pg_typemap_all_strings;
208
- this->encoder_for_put_copy_data = Qnil;
209
- this->decoder_for_get_copy_data = Qnil;
210
- this->trace_stream = Qnil;
211
- this->external_encoding = Qnil;
258
+ RB_OBJ_WRITE(self, &this->socket_io, Qnil);
259
+ RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
260
+ RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
261
+ RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
262
+ RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
263
+ RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
264
+ RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, Qnil);
265
+ RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
266
+ rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
212
267
 
213
268
  return self;
214
269
  }
215
270
 
216
-
217
- /*
218
- * Document-method: new
219
- *
220
- * call-seq:
221
- * PG::Connection.new -> conn
222
- * PG::Connection.new(connection_hash) -> conn
223
- * PG::Connection.new(connection_string) -> conn
224
- * PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
225
- *
226
- * Create a connection to the specified server.
227
- *
228
- * [+host+]
229
- * server hostname
230
- * [+hostaddr+]
231
- * server address (avoids hostname lookup, overrides +host+)
232
- * [+port+]
233
- * server port number
234
- * [+dbname+]
235
- * connecting database name
236
- * [+user+]
237
- * login user name
238
- * [+password+]
239
- * login password
240
- * [+connect_timeout+]
241
- * maximum time to wait for connection to succeed
242
- * [+options+]
243
- * backend options
244
- * [+tty+]
245
- * (ignored in newer versions of PostgreSQL)
246
- * [+sslmode+]
247
- * (disable|allow|prefer|require)
248
- * [+krbsrvname+]
249
- * kerberos service name
250
- * [+gsslib+]
251
- * GSS library to use for GSSAPI authentication
252
- * [+service+]
253
- * service name to use for additional parameters
254
- *
255
- * Examples:
256
- *
257
- * # Connect using all defaults
258
- * PG::Connection.new
259
- *
260
- * # As a Hash
261
- * PG::Connection.new( :dbname => 'test', :port => 5432 )
262
- *
263
- * # As a String
264
- * PG::Connection.new( "dbname=test port=5432" )
265
- *
266
- * # As an Array
267
- * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
268
- *
269
- * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
270
- * connection will have its +client_encoding+ set accordingly.
271
- *
272
- * Raises a PG::Error if the connection fails.
273
- */
274
271
  static VALUE
275
- pgconn_init(int argc, VALUE *argv, VALUE self)
272
+ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
276
273
  {
277
274
  t_pg_connection *this;
278
275
  VALUE conninfo;
279
- VALUE error;
276
+ VALUE self = pgconn_s_allocate( klass );
280
277
 
281
278
  this = pg_get_connection( self );
282
279
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
283
280
  this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
284
281
 
285
282
  if(this->pgconn == NULL)
286
- rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
283
+ rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
287
284
 
288
- if (PQstatus(this->pgconn) == CONNECTION_BAD) {
289
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
290
- rb_iv_set(error, "@connection", self);
291
- rb_exc_raise(error);
292
- }
285
+ if (PQstatus(this->pgconn) == CONNECTION_BAD)
286
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
293
287
 
294
- #ifdef M17N_SUPPORTED
295
288
  pgconn_set_default_encoding( self );
296
- #endif
297
289
 
298
290
  if (rb_block_given_p()) {
299
291
  return rb_ensure(rb_yield, self, pgconn_finish, self);
@@ -307,14 +299,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
307
299
  * PG::Connection.connect_start(connection_string) -> conn
308
300
  * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
309
301
  *
310
- * This is an asynchronous version of PG::Connection.connect().
302
+ * This is an asynchronous version of PG::Connection.new.
311
303
  *
312
304
  * Use #connect_poll to poll the status of the connection.
313
305
  *
314
306
  * NOTE: this does *not* set the connection's +client_encoding+ for you if
315
- * Encoding.default_internal is set. To set it after the connection is established,
307
+ * +Encoding.default_internal+ is set. To set it after the connection is established,
316
308
  * call #internal_encoding=. You can also set it automatically by setting
317
- * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
309
+ * <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
310
+ *
311
+ * See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
318
312
  *
319
313
  */
320
314
  static VALUE
@@ -322,7 +316,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
322
316
  {
323
317
  VALUE rb_conn;
324
318
  VALUE conninfo;
325
- VALUE error;
326
319
  t_pg_connection *this;
327
320
 
328
321
  /*
@@ -335,13 +328,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
335
328
  this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
336
329
 
337
330
  if( this->pgconn == NULL )
338
- rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
331
+ rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
339
332
 
340
- if ( PQstatus(this->pgconn) == CONNECTION_BAD ) {
341
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
342
- rb_iv_set(error, "@connection", rb_conn);
343
- rb_exc_raise(error);
344
- }
333
+ if ( PQstatus(this->pgconn) == CONNECTION_BAD )
334
+ pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
345
335
 
346
336
  if ( rb_block_given_p() ) {
347
337
  return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
@@ -349,37 +339,17 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
349
339
  return rb_conn;
350
340
  }
351
341
 
352
- #ifdef HAVE_PQPING
353
- /*
354
- * call-seq:
355
- * PG::Connection.ping(connection_hash) -> Integer
356
- * PG::Connection.ping(connection_string) -> Integer
357
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
358
- *
359
- * Check server status.
360
- *
361
- * Returns one of:
362
- * [+PQPING_OK+]
363
- * server is accepting connections
364
- * [+PQPING_REJECT+]
365
- * server is alive but rejecting connections
366
- * [+PQPING_NO_RESPONSE+]
367
- * could not establish connection
368
- * [+PQPING_NO_ATTEMPT+]
369
- * connection not attempted (bad params)
370
- */
371
342
  static VALUE
372
- pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
343
+ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
373
344
  {
374
345
  PGPing ping;
375
346
  VALUE conninfo;
376
347
 
377
348
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
378
- ping = PQping( StringValueCStr(conninfo) );
349
+ ping = gvl_PQping( StringValueCStr(conninfo) );
379
350
 
380
351
  return INT2FIX((int)ping);
381
352
  }
382
- #endif
383
353
 
384
354
 
385
355
  /*
@@ -417,17 +387,71 @@ pgconn_s_conndefaults(VALUE self)
417
387
  return array;
418
388
  }
419
389
 
390
+ /*
391
+ * Document-method: PG::Connection.conninfo_parse
392
+ *
393
+ * call-seq:
394
+ * PG::Connection.conninfo_parse(conninfo_string) -> Array
395
+ *
396
+ * Returns parsed connection options from the provided connection string as an array of hashes.
397
+ * Each hash has the same keys as PG::Connection.conndefaults() .
398
+ * The values from the +conninfo_string+ are stored in the +:val+ key.
399
+ */
400
+ static VALUE
401
+ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
402
+ {
403
+ VALUE array;
404
+ char *errmsg = NULL;
405
+ PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
406
+ if(errmsg){
407
+ VALUE error = rb_str_new_cstr(errmsg);
408
+ PQfreemem(errmsg);
409
+ rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
410
+ }
411
+ array = pgconn_make_conninfo_array( options );
412
+
413
+ PQconninfoFree(options);
414
+
415
+ UNUSED( self );
416
+
417
+ return array;
418
+ }
419
+
420
+
421
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
422
+ static VALUE
423
+ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
424
+ {
425
+ char *encrypted = NULL;
426
+ VALUE rval = Qnil;
427
+ VALUE password, username, algorithm;
428
+ PGconn *conn = pg_get_pgconn(self);
429
+
430
+ rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
431
+
432
+ Check_Type(password, T_STRING);
433
+ Check_Type(username, T_STRING);
434
+
435
+ encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
436
+ if ( encrypted ) {
437
+ rval = rb_str_new2( encrypted );
438
+ PQfreemem( encrypted );
439
+ } else {
440
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
441
+ }
442
+
443
+ return rval;
444
+ }
445
+ #endif
446
+
420
447
 
421
448
  /*
422
449
  * call-seq:
423
450
  * PG::Connection.encrypt_password( password, username ) -> String
424
451
  *
425
- * This function is intended to be used by client applications that
426
- * send commands like: +ALTER USER joe PASSWORD 'pwd'+.
427
- * The arguments are the cleartext password, and the SQL name
428
- * of the user it is for.
452
+ * This is an older, deprecated version of #encrypt_password.
453
+ * The difference is that this function always uses +md5+ as the encryption algorithm.
429
454
  *
430
- * Return value is the encrypted password.
431
455
  */
432
456
  static VALUE
433
457
  pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
@@ -444,9 +468,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
444
468
  rval = rb_str_new2( encrypted );
445
469
  PQfreemem( encrypted );
446
470
 
447
- OBJ_INFECT( rval, password );
448
- OBJ_INFECT( rval, username );
449
-
450
471
  return rval;
451
472
  }
452
473
 
@@ -470,17 +491,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
470
491
  * the asynchronous connection is ready
471
492
  *
472
493
  * Example:
473
- * conn = PG::Connection.connect_start("dbname=mydatabase")
474
- * socket = conn.socket_io
494
+ * require "io/wait"
495
+ *
496
+ * conn = PG::Connection.connect_start(dbname: 'mydatabase')
475
497
  * status = conn.connect_poll
476
498
  * while(status != PG::PGRES_POLLING_OK) do
477
499
  * # do some work while waiting for the connection to complete
478
500
  * if(status == PG::PGRES_POLLING_READING)
479
- * if(not select([socket], [], [], 10.0))
501
+ * unless conn.socket_io.wait_readable(10.0)
480
502
  * raise "Asynchronous connection timed out!"
481
503
  * end
482
504
  * elsif(status == PG::PGRES_POLLING_WRITING)
483
- * if(not select([], [socket], [], 10.0))
505
+ * unless conn.socket_io.wait_writable(10.0)
484
506
  * raise "Asynchronous connection timed out!"
485
507
  * end
486
508
  * end
@@ -494,6 +516,9 @@ pgconn_connect_poll(VALUE self)
494
516
  {
495
517
  PostgresPollingStatusType status;
496
518
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
519
+
520
+ pgconn_close_socket_io(self);
521
+
497
522
  return INT2FIX((int)status);
498
523
  }
499
524
 
@@ -530,15 +555,8 @@ pgconn_finished_p( VALUE self )
530
555
  }
531
556
 
532
557
 
533
- /*
534
- * call-seq:
535
- * conn.reset()
536
- *
537
- * Resets the backend connection. This method closes the
538
- * backend connection and tries to re-connect.
539
- */
540
558
  static VALUE
541
- pgconn_reset( VALUE self )
559
+ pgconn_sync_reset( VALUE self )
542
560
  {
543
561
  pgconn_close_socket_io( self );
544
562
  gvl_PQreset( pg_get_pgconn(self) );
@@ -560,7 +578,7 @@ pgconn_reset_start(VALUE self)
560
578
  {
561
579
  pgconn_close_socket_io( self );
562
580
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
563
- rb_raise(rb_eUnableToSend, "reset has failed");
581
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
564
582
  return Qnil;
565
583
  }
566
584
 
@@ -577,6 +595,9 @@ pgconn_reset_poll(VALUE self)
577
595
  {
578
596
  PostgresPollingStatusType status;
579
597
  status = gvl_PQresetPoll(pg_get_pgconn(self));
598
+
599
+ pgconn_close_socket_io(self);
600
+
580
601
  return INT2FIX((int)status);
581
602
  }
582
603
 
@@ -592,7 +613,7 @@ pgconn_db(VALUE self)
592
613
  {
593
614
  char *db = PQdb(pg_get_pgconn(self));
594
615
  if (!db) return Qnil;
595
- return rb_tainted_str_new2(db);
616
+ return rb_str_new2(db);
596
617
  }
597
618
 
598
619
  /*
@@ -606,36 +627,67 @@ pgconn_user(VALUE self)
606
627
  {
607
628
  char *user = PQuser(pg_get_pgconn(self));
608
629
  if (!user) return Qnil;
609
- return rb_tainted_str_new2(user);
630
+ return rb_str_new2(user);
610
631
  }
611
632
 
612
633
  /*
613
634
  * call-seq:
614
635
  * conn.pass()
615
636
  *
616
- * Returns the authenticated user name.
637
+ * Returns the authenticated password.
617
638
  */
618
639
  static VALUE
619
640
  pgconn_pass(VALUE self)
620
641
  {
621
642
  char *user = PQpass(pg_get_pgconn(self));
622
643
  if (!user) return Qnil;
623
- return rb_tainted_str_new2(user);
644
+ return rb_str_new2(user);
624
645
  }
625
646
 
626
647
  /*
627
648
  * call-seq:
628
649
  * conn.host()
629
650
  *
630
- * Returns the connected server name.
651
+ * Returns the server host name of the active connection.
652
+ * This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
653
+ * (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
654
+ *
655
+ * If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
656
+ * If only hostaddr was specified, then that is returned.
657
+ * If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
658
+ *
659
+ * 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.
660
+ *
661
+ * 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.
662
+ * The status of the connection can be checked using the function Connection#status .
631
663
  */
632
664
  static VALUE
633
665
  pgconn_host(VALUE self)
634
666
  {
635
667
  char *host = PQhost(pg_get_pgconn(self));
636
668
  if (!host) return Qnil;
637
- return rb_tainted_str_new2(host);
669
+ return rb_str_new2(host);
670
+ }
671
+
672
+ /* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
673
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
674
+ /*
675
+ * call-seq:
676
+ * conn.hostaddr()
677
+ *
678
+ * Returns the server IP address of the active connection.
679
+ * This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
680
+ * 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.
681
+ *
682
+ */
683
+ static VALUE
684
+ pgconn_hostaddr(VALUE self)
685
+ {
686
+ char *host = PQhostaddr(pg_get_pgconn(self));
687
+ if (!host) return Qnil;
688
+ return rb_str_new2(host);
638
689
  }
690
+ #endif
639
691
 
640
692
  /*
641
693
  * call-seq:
@@ -647,21 +699,22 @@ static VALUE
647
699
  pgconn_port(VALUE self)
648
700
  {
649
701
  char* port = PQport(pg_get_pgconn(self));
650
- return INT2NUM(atol(port));
702
+ if (!port || port[0] == '\0')
703
+ return INT2NUM(DEF_PGPORT);
704
+ else
705
+ return INT2NUM(atoi(port));
651
706
  }
652
707
 
653
708
  /*
654
709
  * call-seq:
655
710
  * conn.tty()
656
711
  *
657
- * Returns the connected pgtty. (Obsolete)
712
+ * Obsolete function.
658
713
  */
659
714
  static VALUE
660
715
  pgconn_tty(VALUE self)
661
716
  {
662
- char *tty = PQtty(pg_get_pgconn(self));
663
- if (!tty) return Qnil;
664
- return rb_tainted_str_new2(tty);
717
+ return rb_str_new2("");
665
718
  }
666
719
 
667
720
  /*
@@ -675,17 +728,17 @@ pgconn_options(VALUE self)
675
728
  {
676
729
  char *options = PQoptions(pg_get_pgconn(self));
677
730
  if (!options) return Qnil;
678
- return rb_tainted_str_new2(options);
731
+ return rb_str_new2(options);
679
732
  }
680
733
 
681
734
 
682
- #ifdef HAVE_PQCONNINFO
683
735
  /*
684
736
  * call-seq:
685
737
  * conn.conninfo -> hash
686
738
  *
687
739
  * Returns the connection options used by a live connection.
688
740
  *
741
+ * Available since PostgreSQL-9.3
689
742
  */
690
743
  static VALUE
691
744
  pgconn_conninfo( VALUE self )
@@ -698,14 +751,24 @@ pgconn_conninfo( VALUE self )
698
751
 
699
752
  return array;
700
753
  }
701
- #endif
702
754
 
703
755
 
704
756
  /*
705
757
  * call-seq:
706
758
  * conn.status()
707
759
  *
708
- * 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
+ * This method returns the status of the last command from memory.
767
+ * It doesn't do any socket access hence is not suitable to test the connectivity.
768
+ * See check_socket for a way to verify the socket state.
769
+ *
770
+ * Example:
771
+ * PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
709
772
  */
710
773
  static VALUE
711
774
  pgconn_status(VALUE self)
@@ -755,7 +818,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
755
818
  if(ret == NULL)
756
819
  return Qnil;
757
820
  else
758
- return rb_tainted_str_new2(ret);
821
+ return rb_str_new2(ret);
759
822
  }
760
823
 
761
824
  /*
@@ -793,20 +856,25 @@ pgconn_server_version(VALUE self)
793
856
  * call-seq:
794
857
  * conn.error_message -> String
795
858
  *
796
- * Returns the error message about connection.
859
+ * Returns the error message most recently generated by an operation on the connection.
860
+ *
861
+ * Nearly all libpq functions will set a message for conn.error_message if they fail.
862
+ * Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
797
863
  */
798
864
  static VALUE
799
865
  pgconn_error_message(VALUE self)
800
866
  {
801
867
  char *error = PQerrorMessage(pg_get_pgconn(self));
802
868
  if (!error) return Qnil;
803
- return rb_tainted_str_new2(error);
869
+ return rb_str_new2(error);
804
870
  }
805
871
 
806
872
  /*
807
873
  * call-seq:
808
874
  * conn.socket() -> Integer
809
875
  *
876
+ * This method is deprecated. Please use the more portable method #socket_io .
877
+ *
810
878
  * Returns the socket's file descriptor for this connection.
811
879
  * <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
812
880
  * If you do so, you will likely also want to set <tt>autoclose=false</tt>
@@ -815,69 +883,71 @@ pgconn_error_message(VALUE self)
815
883
  * creates an IO that's associated with the connection object itself,
816
884
  * and so won't go out of scope until the connection does.
817
885
  *
818
- * *Note:* On Windows the file descriptor is not really usable,
886
+ * *Note:* On Windows the file descriptor is not usable,
819
887
  * since it can not be used to build a Ruby IO object.
820
888
  */
821
889
  static VALUE
822
890
  pgconn_socket(VALUE self)
823
891
  {
824
892
  int sd;
893
+ pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
894
+
825
895
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
826
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
896
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
897
+
827
898
  return INT2NUM(sd);
828
899
  }
829
900
 
830
-
831
- #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
832
-
833
901
  /*
834
902
  * call-seq:
835
903
  * conn.socket_io() -> IO
836
904
  *
837
- * Fetch a memoized IO object created from the Connection's underlying socket.
838
- * This object can be used for IO.select to wait for events while running
839
- * asynchronous API calls.
905
+ * Fetch an IO object created from the Connection's underlying socket.
906
+ * 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.
907
+ * <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
840
908
  *
841
- * Using this instead of #socket avoids the problem of the underlying connection
842
- * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
843
- * goes out of scope.
909
+ * The IO object can change while the connection is established, but is memorized afterwards.
910
+ * So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
844
911
  *
845
- * This method can also be used on Windows but requires Ruby-2.0+.
912
+ * Using this method also works on Windows in contrast to using #socket .
913
+ * 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.
846
914
  */
847
915
  static VALUE
848
916
  pgconn_socket_io(VALUE self)
849
917
  {
850
918
  int sd;
851
919
  int ruby_sd;
852
- ID id_autoclose = rb_intern("autoclose=");
853
920
  t_pg_connection *this = pg_get_connection_safe( self );
921
+ VALUE cSocket;
854
922
  VALUE socket_io = this->socket_io;
855
923
 
856
924
  if ( !RTEST(socket_io) ) {
857
- if( (sd = PQsocket(this->pgconn)) < 0)
858
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
925
+ if( (sd = PQsocket(this->pgconn)) < 0){
926
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
927
+ }
859
928
 
860
929
  #ifdef _WIN32
861
930
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
931
+ if( ruby_sd == -1 )
932
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
933
+
934
+ this->ruby_sd = ruby_sd;
862
935
  #else
863
936
  ruby_sd = sd;
864
937
  #endif
865
938
 
866
- socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
939
+ cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
940
+ socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
867
941
 
868
- /* Disable autoclose feature, when supported */
869
- if( rb_respond_to(socket_io, id_autoclose) ){
870
- rb_funcall( socket_io, id_autoclose, 1, Qfalse );
871
- }
942
+ /* Disable autoclose feature */
943
+ rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
872
944
 
873
- this->socket_io = socket_io;
945
+ RB_OBJ_WRITE(self, &this->socket_io, socket_io);
874
946
  }
875
947
 
876
948
  return socket_io;
877
949
  }
878
950
 
879
- #endif
880
-
881
951
  /*
882
952
  * call-seq:
883
953
  * conn.backend_pid() -> Integer
@@ -892,6 +962,51 @@ pgconn_backend_pid(VALUE self)
892
962
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
893
963
  }
894
964
 
965
+ typedef struct
966
+ {
967
+ struct sockaddr_storage addr;
968
+ socklen_t salen;
969
+ } SockAddr;
970
+
971
+ /* Copy of struct pg_cancel from libpq-int.h
972
+ *
973
+ * See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
974
+ */
975
+ struct pg_cancel
976
+ {
977
+ SockAddr raddr; /* Remote address */
978
+ int be_pid; /* PID of backend --- needed for cancels */
979
+ int be_key; /* key of backend --- needed for cancels */
980
+ };
981
+
982
+ /*
983
+ * call-seq:
984
+ * conn.backend_key() -> Integer
985
+ *
986
+ * Returns the key of the backend server process for this connection.
987
+ * This key can be used to cancel queries on the server.
988
+ */
989
+ static VALUE
990
+ pgconn_backend_key(VALUE self)
991
+ {
992
+ int be_key;
993
+ struct pg_cancel *cancel;
994
+ PGconn *conn = pg_get_pgconn(self);
995
+
996
+ cancel = (struct pg_cancel*)PQgetCancel(conn);
997
+ if(cancel == NULL)
998
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
999
+
1000
+ if( cancel->be_pid != PQbackendPID(conn) )
1001
+ rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
1002
+
1003
+ be_key = cancel->be_key;
1004
+
1005
+ PQfreeCancel(cancel);
1006
+
1007
+ return INT2NUM(be_key);
1008
+ }
1009
+
895
1010
  /*
896
1011
  * call-seq:
897
1012
  * conn.connection_needs_password() -> Boolean
@@ -922,44 +1037,35 @@ pgconn_connection_used_password(VALUE self)
922
1037
  /* :TODO: get_ssl */
923
1038
 
924
1039
 
925
- static VALUE pgconn_exec_params( int, VALUE *, VALUE );
1040
+ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
926
1041
 
927
1042
  /*
928
1043
  * call-seq:
929
- * conn.exec(sql) -> PG::Result
930
- * conn.exec(sql) {|pg_result| block }
931
- *
932
- * Sends SQL query request specified by _sql_ to PostgreSQL.
933
- * Returns a PG::Result instance on success.
934
- * On failure, it raises a PG::Error.
1044
+ * conn.sync_exec(sql) -> PG::Result
1045
+ * conn.sync_exec(sql) {|pg_result| block }
935
1046
  *
936
- * For backward compatibility, if you pass more than one parameter to this method,
937
- * it will call #exec_params for you. New code should explicitly use #exec_params if
938
- * argument placeholders are used.
1047
+ * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
1048
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
939
1049
  *
940
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
941
- * and the PG::Result object will automatically be cleared when the block terminates.
942
- * In this instance, <code>conn.exec</code> returns the value of the block.
1050
+ * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
1051
+ * However #async_exec has two advantages:
943
1052
  *
944
- * #exec is implemented on the synchronous command processing API of libpq, whereas
945
- * #async_exec is implemented on the asynchronous API.
946
- * #exec is somewhat faster that #async_exec, but blocks any signals to be processed until
947
- * the query is finished. This is most notably visible by a delayed reaction to Control+C.
948
- * Both methods ensure that other threads can process while waiting for the server to
949
- * complete the request.
1053
+ * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
1054
+ * 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
1055
+ * So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
950
1056
  */
951
1057
  static VALUE
952
- pgconn_exec(int argc, VALUE *argv, VALUE self)
1058
+ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
953
1059
  {
954
- PGconn *conn = pg_get_pgconn(self);
1060
+ t_pg_connection *this = pg_get_connection_safe( self );
955
1061
  PGresult *result = NULL;
956
1062
  VALUE rb_pgresult;
957
1063
 
958
- /* If called with no parameters, use PQexec */
959
- if ( argc == 1 ) {
1064
+ /* If called with no or nil parameters, use PQexec for compatibility */
1065
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
960
1066
  VALUE query_str = argv[0];
961
1067
 
962
- result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
1068
+ result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
963
1069
  rb_pgresult = pg_new_result(result, self);
964
1070
  pg_result_check(rb_pgresult);
965
1071
  if (rb_block_given_p()) {
@@ -967,11 +1073,10 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
967
1073
  }
968
1074
  return rb_pgresult;
969
1075
  }
1076
+ pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
970
1077
 
971
1078
  /* Otherwise, just call #exec_params instead for backward-compatibility */
972
- else {
973
- return pgconn_exec_params( argc, argv, self );
974
- }
1079
+ return pgconn_sync_exec_params( argc, argv, self );
975
1080
 
976
1081
  }
977
1082
 
@@ -1003,7 +1108,7 @@ struct query_params_data {
1003
1108
  * Filled by alloc_query_params()
1004
1109
  */
1005
1110
 
1006
- /* Wraps the pointer of allocated memory, if function parameters dont't
1111
+ /* Wraps the pointer of allocated memory, if function parameters don't
1007
1112
  * fit in the memory_pool below.
1008
1113
  */
1009
1114
  VALUE heap_pool;
@@ -1021,7 +1126,7 @@ struct query_params_data {
1021
1126
  Oid *types;
1022
1127
 
1023
1128
  /* This array takes the string values for the timeframe of the query,
1024
- * if param value convertion is required
1129
+ * if param value conversion is required
1025
1130
  */
1026
1131
  VALUE gc_array;
1027
1132
 
@@ -1035,8 +1140,9 @@ struct query_params_data {
1035
1140
  };
1036
1141
 
1037
1142
  static void
1038
- free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1143
+ free_typecast_heap_chain(void *_chain_entry)
1039
1144
  {
1145
+ struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
1040
1146
  while(chain_entry){
1041
1147
  struct linked_typecast_data *next = chain_entry->next;
1042
1148
  xfree(chain_entry);
@@ -1044,6 +1150,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1044
1150
  }
1045
1151
  }
1046
1152
 
1153
+ static const rb_data_type_t pg_typecast_buffer_type = {
1154
+ "PG::Connection typecast buffer chain",
1155
+ {
1156
+ (RUBY_DATA_FUNC) NULL,
1157
+ free_typecast_heap_chain,
1158
+ (size_t (*)(const void *))NULL,
1159
+ },
1160
+ 0,
1161
+ 0,
1162
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1163
+ };
1164
+
1047
1165
  static char *
1048
1166
  alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1049
1167
  {
@@ -1054,17 +1172,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1054
1172
  /* Did we already wrap a memory chain per T_DATA object? */
1055
1173
  if( NIL_P( *typecast_heap_chain ) ){
1056
1174
  /* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
1057
- *typecast_heap_chain = Data_Wrap_Struct( rb_cObject, NULL, free_typecast_heap_chain, allocated );
1175
+ *typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
1058
1176
  allocated->next = NULL;
1059
1177
  } else {
1060
1178
  /* Append to the chain */
1061
- allocated->next = DATA_PTR( *typecast_heap_chain );
1062
- DATA_PTR( *typecast_heap_chain ) = allocated;
1179
+ allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
1180
+ RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
1063
1181
  }
1064
1182
 
1065
1183
  return &allocated->data[0];
1066
1184
  }
1067
1185
 
1186
+ static const rb_data_type_t pg_query_heap_pool_type = {
1187
+ "PG::Connection query heap pool",
1188
+ {
1189
+ (RUBY_DATA_FUNC) NULL,
1190
+ RUBY_TYPED_DEFAULT_FREE,
1191
+ (size_t (*)(const void *))NULL,
1192
+ },
1193
+ 0,
1194
+ 0,
1195
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1196
+ };
1068
1197
 
1069
1198
  static int
1070
1199
  alloc_query_params(struct query_params_data *paramsData)
@@ -1079,7 +1208,7 @@ alloc_query_params(struct query_params_data *paramsData)
1079
1208
 
1080
1209
  Check_Type(paramsData->params, T_ARRAY);
1081
1210
 
1082
- p_typemap = DATA_PTR( paramsData->typemap );
1211
+ p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
1083
1212
  p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
1084
1213
 
1085
1214
  paramsData->heap_pool = Qnil;
@@ -1098,7 +1227,7 @@ alloc_query_params(struct query_params_data *paramsData)
1098
1227
  /* Allocate one combined memory pool for all possible function parameters */
1099
1228
  memory_pool = (char*)xmalloc( required_pool_size );
1100
1229
  /* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
1101
- paramsData->heap_pool = Data_Wrap_Struct( rb_cObject, NULL, -1, memory_pool );
1230
+ paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
1102
1231
  required_pool_size = 0;
1103
1232
  }else{
1104
1233
  /* Use stack memory for function parameters */
@@ -1211,85 +1340,52 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1211
1340
  /* Use default typemap for queries. It's type is checked when assigned. */
1212
1341
  paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
1213
1342
  }else{
1343
+ t_typemap *tm;
1344
+ UNUSED(tm);
1345
+
1214
1346
  /* Check type of method param */
1215
- if ( !rb_obj_is_kind_of(paramsData->typemap, rb_cTypeMap) ) {
1216
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1217
- rb_obj_classname( paramsData->typemap ) );
1218
- }
1219
- Check_Type( paramsData->typemap, T_DATA );
1347
+ TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
1220
1348
  }
1221
1349
  }
1222
1350
 
1223
1351
  /*
1224
1352
  * call-seq:
1225
- * conn.exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1226
- * conn.exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1227
- *
1228
- * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
1229
- * for parameters.
1230
- *
1231
- * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
1232
- *
1233
- * +params+ is an array of the bind parameters for the SQL query.
1234
- * Each element of the +params+ array may be either:
1235
- * a hash of the form:
1236
- * {:value => String (value of bind parameter)
1237
- * :type => Integer (oid of type of bind parameter)
1238
- * :format => Integer (0 for text, 1 for binary)
1239
- * }
1240
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1241
- * { :value => <string value>, :type => 0, :format => 0 }
1242
- *
1243
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1244
- * inside the SQL query. The 0th element of the +params+ array is bound
1245
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1246
- *
1247
- * If the types are not specified, they will be inferred by PostgreSQL.
1248
- * Instead of specifying type oids, it's recommended to simply add
1249
- * explicit casts in the query to ensure that the right type is used.
1250
- *
1251
- * For example: "SELECT $1::int"
1353
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1354
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1252
1355
  *
1253
- * The optional +result_format+ should be 0 for text results, 1
1254
- * for binary.
1255
- *
1256
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1257
- * This will type cast the params form various Ruby types before transmission
1258
- * based on the encoders defined by the type map. When a type encoder is used
1259
- * the format and oid of a given bind parameter are retrieved from the encoder
1260
- * instead out of the hash form described above.
1261
- *
1262
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1263
- * and the PG::Result object will automatically be cleared when the block terminates.
1264
- * In this instance, <code>conn.exec</code> returns the value of the block.
1356
+ * This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
1357
+ * See #async_exec for the differences between the two API variants.
1358
+ * It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
1265
1359
  */
1266
1360
  static VALUE
1267
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1361
+ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1268
1362
  {
1269
- PGconn *conn = pg_get_pgconn(self);
1363
+ t_pg_connection *this = pg_get_connection_safe( self );
1270
1364
  PGresult *result = NULL;
1271
1365
  VALUE rb_pgresult;
1272
1366
  VALUE command, in_res_fmt;
1273
1367
  int nParams;
1274
1368
  int resultFormat;
1275
- struct query_params_data paramsData = { ENCODING_GET(self) };
1369
+ struct query_params_data paramsData = { this->enc_idx };
1276
1370
 
1371
+ /* For compatibility we accept 1 to 4 parameters */
1277
1372
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1278
1373
  paramsData.with_types = 1;
1279
1374
 
1280
1375
  /*
1281
- * Handle the edge-case where the caller is coming from #exec, but passed an explict +nil+
1282
- * for the second parameter.
1376
+ * For backward compatibility no or +nil+ for the second parameter
1377
+ * is passed to #exec
1283
1378
  */
1284
1379
  if ( NIL_P(paramsData.params) ) {
1285
- return pgconn_exec( 1, argv, self );
1380
+ pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1381
+ return pgconn_sync_exec( 1, argv, self );
1286
1382
  }
1287
1383
  pgconn_query_assign_typemap( self, &paramsData );
1288
1384
 
1289
1385
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1290
1386
  nParams = alloc_query_params( &paramsData );
1291
1387
 
1292
- result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1388
+ result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1293
1389
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1294
1390
 
1295
1391
  free_query_params( &paramsData );
@@ -1306,28 +1402,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1306
1402
 
1307
1403
  /*
1308
1404
  * call-seq:
1309
- * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1310
- *
1311
- * Prepares statement _sql_ with name _name_ to be executed later.
1312
- * Returns a PG::Result instance on success.
1313
- * On failure, it raises a PG::Error.
1314
- *
1315
- * +param_types+ is an optional parameter to specify the Oids of the
1316
- * types of the parameters.
1317
- *
1318
- * If the types are not specified, they will be inferred by PostgreSQL.
1319
- * Instead of specifying type oids, it's recommended to simply add
1320
- * explicit casts in the query to ensure that the right type is used.
1405
+ * conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1321
1406
  *
1322
- * For example: "SELECT $1::int"
1323
- *
1324
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1325
- * inside the SQL query.
1407
+ * This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
1408
+ * See #async_exec for the differences between the two API variants.
1409
+ * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1326
1410
  */
1327
1411
  static VALUE
1328
- pgconn_prepare(int argc, VALUE *argv, VALUE self)
1412
+ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1329
1413
  {
1330
- PGconn *conn = pg_get_pgconn(self);
1414
+ t_pg_connection *this = pg_get_connection_safe( self );
1331
1415
  PGresult *result = NULL;
1332
1416
  VALUE rb_pgresult;
1333
1417
  VALUE name, command, in_paramtypes;
@@ -1337,7 +1421,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1337
1421
  Oid *paramTypes = NULL;
1338
1422
  const char *name_cstr;
1339
1423
  const char *command_cstr;
1340
- int enc_idx = ENCODING_GET(self);
1424
+ int enc_idx = this->enc_idx;
1341
1425
 
1342
1426
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1343
1427
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1355,7 +1439,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1355
1439
  paramTypes[i] = NUM2UINT(param);
1356
1440
  }
1357
1441
  }
1358
- result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1442
+ result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1359
1443
 
1360
1444
  xfree(paramTypes);
1361
1445
 
@@ -1366,49 +1450,23 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1366
1450
 
1367
1451
  /*
1368
1452
  * call-seq:
1369
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1370
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1371
- *
1372
- * Execute prepared named statement specified by _statement_name_.
1373
- * Returns a PG::Result instance on success.
1374
- * On failure, it raises a PG::Error.
1375
- *
1376
- * +params+ is an array of the optional bind parameters for the
1377
- * SQL query. Each element of the +params+ array may be either:
1378
- * a hash of the form:
1379
- * {:value => String (value of bind parameter)
1380
- * :format => Integer (0 for text, 1 for binary)
1381
- * }
1382
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1383
- * { :value => <string value>, :format => 0 }
1384
- *
1385
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1386
- * inside the SQL query. The 0th element of the +params+ array is bound
1387
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1388
- *
1389
- * The optional +result_format+ should be 0 for text results, 1
1390
- * for binary.
1391
- *
1392
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1393
- * This will type cast the params form various Ruby types before transmission
1394
- * based on the encoders defined by the type map. When a type encoder is used
1395
- * the format and oid of a given bind parameter are retrieved from the encoder
1396
- * instead out of the hash form described above.
1453
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1454
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1397
1455
  *
1398
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1399
- * and the PG::Result object will automatically be cleared when the block terminates.
1400
- * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
1456
+ * This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
1457
+ * See #async_exec for the differences between the two API variants.
1458
+ * It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
1401
1459
  */
1402
1460
  static VALUE
1403
- pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1461
+ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1404
1462
  {
1405
- PGconn *conn = pg_get_pgconn(self);
1463
+ t_pg_connection *this = pg_get_connection_safe( self );
1406
1464
  PGresult *result = NULL;
1407
1465
  VALUE rb_pgresult;
1408
1466
  VALUE name, in_res_fmt;
1409
1467
  int nParams;
1410
1468
  int resultFormat;
1411
- struct query_params_data paramsData = { ENCODING_GET(self) };
1469
+ struct query_params_data paramsData = { this->enc_idx };
1412
1470
 
1413
1471
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1414
1472
  paramsData.with_types = 0;
@@ -1421,7 +1479,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1421
1479
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1422
1480
  nParams = alloc_query_params( &paramsData );
1423
1481
 
1424
- result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1482
+ result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1425
1483
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1426
1484
  resultFormat);
1427
1485
 
@@ -1438,25 +1496,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1438
1496
 
1439
1497
  /*
1440
1498
  * call-seq:
1441
- * conn.describe_prepared( statement_name ) -> PG::Result
1499
+ * conn.sync_describe_prepared( statement_name ) -> PG::Result
1442
1500
  *
1443
- * Retrieve information about the prepared statement
1444
- * _statement_name_.
1501
+ * This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
1502
+ * See #async_exec for the differences between the two API variants.
1503
+ * It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
1445
1504
  */
1446
1505
  static VALUE
1447
- pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1506
+ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1448
1507
  {
1449
1508
  PGresult *result;
1450
1509
  VALUE rb_pgresult;
1451
- PGconn *conn = pg_get_pgconn(self);
1510
+ t_pg_connection *this = pg_get_connection_safe( self );
1452
1511
  const char *stmt;
1453
1512
  if(NIL_P(stmt_name)) {
1454
1513
  stmt = NULL;
1455
1514
  }
1456
1515
  else {
1457
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1516
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1458
1517
  }
1459
- result = gvl_PQdescribePrepared(conn, stmt);
1518
+ result = gvl_PQdescribePrepared(this->pgconn, stmt);
1460
1519
  rb_pgresult = pg_new_result(result, self);
1461
1520
  pg_result_check(rb_pgresult);
1462
1521
  return rb_pgresult;
@@ -1465,25 +1524,26 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1465
1524
 
1466
1525
  /*
1467
1526
  * call-seq:
1468
- * conn.describe_portal( portal_name ) -> PG::Result
1527
+ * conn.sync_describe_portal( portal_name ) -> PG::Result
1469
1528
  *
1470
- * Retrieve information about the portal _portal_name_.
1529
+ * This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
1530
+ * See #async_exec for the differences between the two API variants.
1531
+ * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1471
1532
  */
1472
1533
  static VALUE
1473
- pgconn_describe_portal(self, stmt_name)
1474
- VALUE self, stmt_name;
1534
+ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1475
1535
  {
1476
1536
  PGresult *result;
1477
1537
  VALUE rb_pgresult;
1478
- PGconn *conn = pg_get_pgconn(self);
1538
+ t_pg_connection *this = pg_get_connection_safe( self );
1479
1539
  const char *stmt;
1480
1540
  if(NIL_P(stmt_name)) {
1481
1541
  stmt = NULL;
1482
1542
  }
1483
1543
  else {
1484
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1544
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1485
1545
  }
1486
- result = gvl_PQdescribePortal(conn, stmt);
1546
+ result = gvl_PQdescribePortal(this->pgconn, stmt);
1487
1547
  rb_pgresult = pg_new_result(result, self);
1488
1548
  pg_result_check(rb_pgresult);
1489
1549
  return rb_pgresult;
@@ -1505,6 +1565,9 @@ pgconn_describe_portal(self, stmt_name)
1505
1565
  * * +PGRES_NONFATAL_ERROR+
1506
1566
  * * +PGRES_FATAL_ERROR+
1507
1567
  * * +PGRES_COPY_BOTH+
1568
+ * * +PGRES_SINGLE_TUPLE+
1569
+ * * +PGRES_PIPELINE_SYNC+
1570
+ * * +PGRES_PIPELINE_ABORTED+
1508
1571
  */
1509
1572
  static VALUE
1510
1573
  pgconn_make_empty_pgresult(VALUE self, VALUE status)
@@ -1530,13 +1593,15 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1530
1593
  * Consider using exec_params, which avoids the need for passing values
1531
1594
  * inside of SQL commands.
1532
1595
  *
1533
- * Encoding of escaped string will be equal to client encoding of connection.
1596
+ * Character encoding of escaped string will be equal to client encoding of connection.
1534
1597
  *
1535
1598
  * NOTE: This class version of this method can only be used safely in client
1536
1599
  * programs that use a single PostgreSQL connection at a time (in this case it can
1537
1600
  * find out what it needs to know "behind the scenes"). It might give the wrong
1538
1601
  * results if used in programs that use multiple database connections; use the
1539
1602
  * same method on the connection object in such cases.
1603
+ *
1604
+ * See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
1540
1605
  */
1541
1606
  static VALUE
1542
1607
  pgconn_s_escape(VALUE self, VALUE string)
@@ -1547,8 +1612,8 @@ pgconn_s_escape(VALUE self, VALUE string)
1547
1612
  int enc_idx;
1548
1613
  int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1549
1614
 
1550
- Check_Type(string, T_STRING);
1551
- enc_idx = ENCODING_GET( singleton ? string : self );
1615
+ StringValueCStr(string);
1616
+ enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
1552
1617
  if( ENCODING_GET(string) != enc_idx ){
1553
1618
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1554
1619
  }
@@ -1558,14 +1623,13 @@ pgconn_s_escape(VALUE self, VALUE string)
1558
1623
  if( !singleton ) {
1559
1624
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1560
1625
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1561
- if(error) {
1562
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1563
- }
1626
+ if(error)
1627
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1628
+
1564
1629
  } else {
1565
1630
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1566
1631
  }
1567
1632
  rb_str_set_len(result, size);
1568
- OBJ_INFECT(result, string);
1569
1633
 
1570
1634
  return result;
1571
1635
  }
@@ -1611,7 +1675,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1611
1675
  }
1612
1676
 
1613
1677
  ret = rb_str_new((char*)to, to_len - 1);
1614
- OBJ_INFECT(ret, str);
1615
1678
  PQfreemem(to);
1616
1679
  return ret;
1617
1680
  }
@@ -1641,50 +1704,42 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1641
1704
  to = PQunescapeBytea(from, &to_len);
1642
1705
 
1643
1706
  ret = rb_str_new((char*)to, to_len);
1644
- OBJ_INFECT(ret, str);
1645
1707
  PQfreemem(to);
1646
1708
  return ret;
1647
1709
  }
1648
1710
 
1649
- #ifdef HAVE_PQESCAPELITERAL
1650
1711
  /*
1651
1712
  * call-seq:
1652
1713
  * conn.escape_literal( str ) -> String
1653
1714
  *
1654
1715
  * Escape an arbitrary String +str+ as a literal.
1716
+ *
1717
+ * See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
1655
1718
  */
1656
1719
  static VALUE
1657
1720
  pgconn_escape_literal(VALUE self, VALUE string)
1658
1721
  {
1659
- PGconn *conn = pg_get_pgconn(self);
1722
+ t_pg_connection *this = pg_get_connection_safe( self );
1660
1723
  char *escaped = NULL;
1661
- VALUE error;
1662
1724
  VALUE result = Qnil;
1663
- int enc_idx = ENCODING_GET(self);
1725
+ int enc_idx = this->enc_idx;
1664
1726
 
1665
- Check_Type(string, T_STRING);
1727
+ StringValueCStr(string);
1666
1728
  if( ENCODING_GET(string) != enc_idx ){
1667
1729
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1668
1730
  }
1669
1731
 
1670
- escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1732
+ escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1671
1733
  if (escaped == NULL)
1672
- {
1673
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1674
- rb_iv_set(error, "@connection", self);
1675
- rb_exc_raise(error);
1676
- return Qnil;
1677
- }
1734
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1735
+
1678
1736
  result = rb_str_new2(escaped);
1679
1737
  PQfreemem(escaped);
1680
- OBJ_INFECT(result, string);
1681
1738
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1682
1739
 
1683
1740
  return result;
1684
1741
  }
1685
- #endif
1686
1742
 
1687
- #ifdef HAVE_PQESCAPEIDENTIFIER
1688
1743
  /*
1689
1744
  * call-seq:
1690
1745
  * conn.escape_identifier( str ) -> String
@@ -1698,35 +1753,27 @@ pgconn_escape_literal(VALUE self, VALUE string)
1698
1753
  static VALUE
1699
1754
  pgconn_escape_identifier(VALUE self, VALUE string)
1700
1755
  {
1701
- PGconn *conn = pg_get_pgconn(self);
1756
+ t_pg_connection *this = pg_get_connection_safe( self );
1702
1757
  char *escaped = NULL;
1703
- VALUE error;
1704
1758
  VALUE result = Qnil;
1705
- int enc_idx = ENCODING_GET(self);
1759
+ int enc_idx = this->enc_idx;
1706
1760
 
1707
- Check_Type(string, T_STRING);
1761
+ StringValueCStr(string);
1708
1762
  if( ENCODING_GET(string) != enc_idx ){
1709
1763
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1710
1764
  }
1711
1765
 
1712
- escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1766
+ escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1713
1767
  if (escaped == NULL)
1714
- {
1715
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1716
- rb_iv_set(error, "@connection", self);
1717
- rb_exc_raise(error);
1718
- return Qnil;
1719
- }
1768
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1769
+
1720
1770
  result = rb_str_new2(escaped);
1721
1771
  PQfreemem(escaped);
1722
- OBJ_INFECT(result, string);
1723
1772
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1724
1773
 
1725
1774
  return result;
1726
1775
  }
1727
- #endif
1728
1776
 
1729
- #ifdef HAVE_PQSETSINGLEROWMODE
1730
1777
  /*
1731
1778
  * call-seq:
1732
1779
  * conn.set_single_row_mode -> self
@@ -1762,34 +1809,65 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1762
1809
  * # do something with the received row
1763
1810
  * end
1764
1811
  * end
1765
- *
1766
1812
  */
1767
1813
  static VALUE
1768
1814
  pgconn_set_single_row_mode(VALUE self)
1769
1815
  {
1770
1816
  PGconn *conn = pg_get_pgconn(self);
1771
- VALUE error;
1772
1817
 
1818
+ rb_check_frozen(self);
1773
1819
  if( PQsetSingleRowMode(conn) == 0 )
1774
- {
1775
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1776
- rb_iv_set(error, "@connection", self);
1777
- rb_exc_raise(error);
1778
- }
1820
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1779
1821
 
1780
1822
  return self;
1781
1823
  }
1782
- #endif
1824
+
1825
+ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1826
+
1827
+ /*
1828
+ * call-seq:
1829
+ * conn.send_query(sql) -> nil
1830
+ *
1831
+ * Sends SQL query request specified by _sql_ to PostgreSQL for
1832
+ * asynchronous processing, and immediately returns.
1833
+ * On failure, it raises a PG::Error.
1834
+ *
1835
+ * For backward compatibility, if you pass more than one parameter to this method,
1836
+ * it will call #send_query_params for you. New code should explicitly use #send_query_params if
1837
+ * argument placeholders are used.
1838
+ *
1839
+ */
1840
+ static VALUE
1841
+ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1842
+ {
1843
+ t_pg_connection *this = pg_get_connection_safe( self );
1844
+
1845
+ /* If called with no or nil parameters, use PQexec for compatibility */
1846
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1847
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
1848
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1849
+
1850
+ pgconn_wait_for_flush( self );
1851
+ return Qnil;
1852
+ }
1853
+
1854
+ pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
1855
+
1856
+ /* If called with parameters, and optionally result_format,
1857
+ * use PQsendQueryParams
1858
+ */
1859
+ return pgconn_send_query_params( argc, argv, self);
1860
+ }
1783
1861
 
1784
1862
  /*
1785
1863
  * call-seq:
1786
- * conn.send_query(sql [, params, result_format[, type_map ]] ) -> nil
1864
+ * conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
1787
1865
  *
1788
1866
  * Sends SQL query request specified by _sql_ to PostgreSQL for
1789
1867
  * asynchronous processing, and immediately returns.
1790
1868
  * On failure, it raises a PG::Error.
1791
1869
  *
1792
- * +params+ is an optional array of the bind parameters for the SQL query.
1870
+ * +params+ is an array of the bind parameters for the SQL query.
1793
1871
  * Each element of the +params+ array may be either:
1794
1872
  * a hash of the form:
1795
1873
  * {:value => String (value of bind parameter)
@@ -1799,7 +1877,7 @@ pgconn_set_single_row_mode(VALUE self)
1799
1877
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1800
1878
  * { :value => <string value>, :type => 0, :format => 0 }
1801
1879
  *
1802
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1880
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1803
1881
  * inside the SQL query. The 0th element of the +params+ array is bound
1804
1882
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1805
1883
  *
@@ -1812,55 +1890,39 @@ pgconn_set_single_row_mode(VALUE self)
1812
1890
  * The optional +result_format+ should be 0 for text results, 1
1813
1891
  * for binary.
1814
1892
  *
1815
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1816
- * This will type cast the params form various Ruby types before transmission
1893
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1894
+ * This will type cast the params from various Ruby types before transmission
1817
1895
  * based on the encoders defined by the type map. When a type encoder is used
1818
1896
  * the format and oid of a given bind parameter are retrieved from the encoder
1819
1897
  * instead out of the hash form described above.
1820
1898
  *
1821
1899
  */
1822
1900
  static VALUE
1823
- pgconn_send_query(int argc, VALUE *argv, VALUE self)
1901
+ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1824
1902
  {
1825
- PGconn *conn = pg_get_pgconn(self);
1903
+ t_pg_connection *this = pg_get_connection_safe( self );
1826
1904
  int result;
1827
1905
  VALUE command, in_res_fmt;
1828
- VALUE error;
1829
1906
  int nParams;
1830
1907
  int resultFormat;
1831
- struct query_params_data paramsData = { ENCODING_GET(self) };
1908
+ struct query_params_data paramsData = { this->enc_idx };
1832
1909
 
1833
- rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1910
+ rb_scan_args(argc, argv, "22", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1834
1911
  paramsData.with_types = 1;
1835
1912
 
1836
- /* If called with no parameters, use PQsendQuery */
1837
- if(NIL_P(paramsData.params)) {
1838
- if(gvl_PQsendQuery(conn, pg_cstr_enc(command, paramsData.enc_idx)) == 0) {
1839
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1840
- rb_iv_set(error, "@connection", self);
1841
- rb_exc_raise(error);
1842
- }
1843
- return Qnil;
1844
- }
1845
-
1846
- /* If called with parameters, and optionally result_format,
1847
- * use PQsendQueryParams
1848
- */
1849
-
1850
1913
  pgconn_query_assign_typemap( self, &paramsData );
1851
1914
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1852
1915
  nParams = alloc_query_params( &paramsData );
1853
1916
 
1854
- result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1917
+ result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1855
1918
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1856
1919
 
1857
1920
  free_query_params( &paramsData );
1858
1921
 
1859
- if(result == 0) {
1860
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1861
- rb_iv_set(error, "@connection", self);
1862
- rb_exc_raise(error);
1863
- }
1922
+ if(result == 0)
1923
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1924
+
1925
+ pgconn_wait_for_flush( self );
1864
1926
  return Qnil;
1865
1927
  }
1866
1928
 
@@ -1881,23 +1943,22 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1881
1943
  *
1882
1944
  * For example: "SELECT $1::int"
1883
1945
  *
1884
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1946
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1885
1947
  * inside the SQL query.
1886
1948
  */
1887
1949
  static VALUE
1888
1950
  pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1889
1951
  {
1890
- PGconn *conn = pg_get_pgconn(self);
1952
+ t_pg_connection *this = pg_get_connection_safe( self );
1891
1953
  int result;
1892
1954
  VALUE name, command, in_paramtypes;
1893
1955
  VALUE param;
1894
- VALUE error;
1895
1956
  int i = 0;
1896
1957
  int nParams = 0;
1897
1958
  Oid *paramTypes = NULL;
1898
1959
  const char *name_cstr;
1899
1960
  const char *command_cstr;
1900
- int enc_idx = ENCODING_GET(self);
1961
+ int enc_idx = this->enc_idx;
1901
1962
 
1902
1963
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1903
1964
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1915,15 +1976,14 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1915
1976
  paramTypes[i] = NUM2UINT(param);
1916
1977
  }
1917
1978
  }
1918
- result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1979
+ result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1919
1980
 
1920
1981
  xfree(paramTypes);
1921
1982
 
1922
1983
  if(result == 0) {
1923
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1924
- rb_iv_set(error, "@connection", self);
1925
- rb_exc_raise(error);
1984
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1926
1985
  }
1986
+ pgconn_wait_for_flush( self );
1927
1987
  return Qnil;
1928
1988
  }
1929
1989
 
@@ -1945,15 +2005,15 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1945
2005
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1946
2006
  * { :value => <string value>, :format => 0 }
1947
2007
  *
1948
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
2008
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1949
2009
  * inside the SQL query. The 0th element of the +params+ array is bound
1950
2010
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1951
2011
  *
1952
2012
  * The optional +result_format+ should be 0 for text results, 1
1953
2013
  * for binary.
1954
2014
  *
1955
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1956
- * This will type cast the params form various Ruby types before transmission
2015
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
2016
+ * This will type cast the params from various Ruby types before transmission
1957
2017
  * based on the encoders defined by the type map. When a type encoder is used
1958
2018
  * the format and oid of a given bind parameter are retrieved from the encoder
1959
2019
  * instead out of the hash form described above.
@@ -1962,37 +2022,34 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1962
2022
  static VALUE
1963
2023
  pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1964
2024
  {
1965
- PGconn *conn = pg_get_pgconn(self);
2025
+ t_pg_connection *this = pg_get_connection_safe( self );
1966
2026
  int result;
1967
2027
  VALUE name, in_res_fmt;
1968
- VALUE error;
1969
2028
  int nParams;
1970
2029
  int resultFormat;
1971
- struct query_params_data paramsData = { ENCODING_GET(self) };
2030
+ struct query_params_data paramsData = { this->enc_idx };
1972
2031
 
1973
2032
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1974
2033
  paramsData.with_types = 0;
1975
2034
 
1976
2035
  if(NIL_P(paramsData.params)) {
1977
2036
  paramsData.params = rb_ary_new2(0);
1978
- resultFormat = 0;
1979
2037
  }
1980
2038
  pgconn_query_assign_typemap( self, &paramsData );
1981
2039
 
1982
2040
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1983
2041
  nParams = alloc_query_params( &paramsData );
1984
2042
 
1985
- result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
2043
+ result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1986
2044
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1987
2045
  resultFormat);
1988
2046
 
1989
2047
  free_query_params( &paramsData );
1990
2048
 
1991
- if(result == 0) {
1992
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1993
- rb_iv_set(error, "@connection", self);
1994
- rb_exc_raise(error);
1995
- }
2049
+ if(result == 0)
2050
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2051
+
2052
+ pgconn_wait_for_flush( self );
1996
2053
  return Qnil;
1997
2054
  }
1998
2055
 
@@ -2006,14 +2063,12 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2006
2063
  static VALUE
2007
2064
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2008
2065
  {
2009
- VALUE error;
2010
- PGconn *conn = pg_get_pgconn(self);
2066
+ t_pg_connection *this = pg_get_connection_safe( self );
2011
2067
  /* returns 0 on failure */
2012
- if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
2013
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2014
- rb_iv_set(error, "@connection", self);
2015
- rb_exc_raise(error);
2016
- }
2068
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
2069
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2070
+
2071
+ pgconn_wait_for_flush( self );
2017
2072
  return Qnil;
2018
2073
  }
2019
2074
 
@@ -2028,36 +2083,18 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2028
2083
  static VALUE
2029
2084
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2030
2085
  {
2031
- VALUE error;
2032
- PGconn *conn = pg_get_pgconn(self);
2086
+ t_pg_connection *this = pg_get_connection_safe( self );
2033
2087
  /* returns 0 on failure */
2034
- if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
2035
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2036
- rb_iv_set(error, "@connection", self);
2037
- rb_exc_raise(error);
2038
- }
2088
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
2089
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2090
+
2091
+ pgconn_wait_for_flush( self );
2039
2092
  return Qnil;
2040
2093
  }
2041
2094
 
2042
2095
 
2043
- /*
2044
- * call-seq:
2045
- * conn.get_result() -> PG::Result
2046
- * conn.get_result() {|pg_result| block }
2047
- *
2048
- * Blocks waiting for the next result from a call to
2049
- * #send_query (or another asynchronous command), and returns
2050
- * it. Returns +nil+ if no more results are available.
2051
- *
2052
- * Note: call this function repeatedly until it returns +nil+, or else
2053
- * you will not be able to issue further commands.
2054
- *
2055
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
2056
- * and the PG::Result object will automatically be cleared when the block terminates.
2057
- * In this instance, <code>conn.exec</code> returns the value of the block.
2058
- */
2059
2096
  static VALUE
2060
- pgconn_get_result(VALUE self)
2097
+ pgconn_sync_get_result(VALUE self)
2061
2098
  {
2062
2099
  PGconn *conn = pg_get_pgconn(self);
2063
2100
  PGresult *result;
@@ -2083,17 +2120,15 @@ pgconn_get_result(VALUE self)
2083
2120
  * or *notifies* to see if the state has changed.
2084
2121
  */
2085
2122
  static VALUE
2086
- pgconn_consume_input(self)
2087
- VALUE self;
2123
+ pgconn_consume_input(VALUE self)
2088
2124
  {
2089
- VALUE error;
2090
2125
  PGconn *conn = pg_get_pgconn(self);
2091
2126
  /* returns 0 on error */
2092
2127
  if(PQconsumeInput(conn) == 0) {
2093
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2094
- rb_iv_set(error, "@connection", self);
2095
- rb_exc_raise(error);
2128
+ pgconn_close_socket_io(self);
2129
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2096
2130
  }
2131
+
2097
2132
  return Qnil;
2098
2133
  }
2099
2134
 
@@ -2102,38 +2137,20 @@ pgconn_consume_input(self)
2102
2137
  * conn.is_busy() -> Boolean
2103
2138
  *
2104
2139
  * Returns +true+ if a command is busy, that is, if
2105
- * PQgetResult would block. Otherwise returns +false+.
2140
+ * #get_result would block. Otherwise returns +false+.
2106
2141
  */
2107
2142
  static VALUE
2108
- pgconn_is_busy(self)
2109
- VALUE self;
2143
+ pgconn_is_busy(VALUE self)
2110
2144
  {
2111
2145
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2112
2146
  }
2113
2147
 
2114
- /*
2115
- * call-seq:
2116
- * conn.setnonblocking(Boolean) -> nil
2117
- *
2118
- * Sets the nonblocking status of the connection.
2119
- * In the blocking state, calls to #send_query
2120
- * will block until the message is sent to the server,
2121
- * but will not wait for the query results.
2122
- * In the nonblocking state, calls to #send_query
2123
- * will return an error if the socket is not ready for
2124
- * writing.
2125
- * Note: This function does not affect #exec, because
2126
- * that function doesn't return until the server has
2127
- * processed the query and returned the results.
2128
- * Returns +nil+.
2129
- */
2130
2148
  static VALUE
2131
- pgconn_setnonblocking(self, state)
2132
- VALUE self, state;
2149
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2133
2150
  {
2134
2151
  int arg;
2135
- VALUE error;
2136
2152
  PGconn *conn = pg_get_pgconn(self);
2153
+ rb_check_frozen(self);
2137
2154
  if(state == Qtrue)
2138
2155
  arg = 1;
2139
2156
  else if (state == Qfalse)
@@ -2141,69 +2158,33 @@ pgconn_setnonblocking(self, state)
2141
2158
  else
2142
2159
  rb_raise(rb_eArgError, "Boolean value expected");
2143
2160
 
2144
- if(PQsetnonblocking(conn, arg) == -1) {
2145
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2146
- rb_iv_set(error, "@connection", self);
2147
- rb_exc_raise(error);
2148
- }
2161
+ if(PQsetnonblocking(conn, arg) == -1)
2162
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2163
+
2149
2164
  return Qnil;
2150
2165
  }
2151
2166
 
2152
2167
 
2153
- /*
2154
- * call-seq:
2155
- * conn.isnonblocking() -> Boolean
2156
- *
2157
- * Returns +true+ if a command is busy, that is, if
2158
- * PQgetResult would block. Otherwise returns +false+.
2159
- */
2160
2168
  static VALUE
2161
- pgconn_isnonblocking(self)
2162
- VALUE self;
2169
+ pgconn_sync_isnonblocking(VALUE self)
2163
2170
  {
2164
2171
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2165
2172
  }
2166
2173
 
2167
- /*
2168
- * call-seq:
2169
- * conn.flush() -> Boolean
2170
- *
2171
- * Attempts to flush any queued output data to the server.
2172
- * Returns +true+ if data is successfully flushed, +false+
2173
- * if not (can only return +false+ if connection is
2174
- * nonblocking.
2175
- * Raises PG::Error if some other failure occurred.
2176
- */
2177
2174
  static VALUE
2178
- pgconn_flush(self)
2179
- VALUE self;
2175
+ pgconn_sync_flush(VALUE self)
2180
2176
  {
2181
2177
  PGconn *conn = pg_get_pgconn(self);
2182
- int ret;
2183
- VALUE error;
2184
- ret = PQflush(conn);
2185
- if(ret == -1) {
2186
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2187
- rb_iv_set(error, "@connection", self);
2188
- rb_exc_raise(error);
2189
- }
2178
+ int ret = PQflush(conn);
2179
+ if(ret == -1)
2180
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2181
+
2190
2182
  return (ret) ? Qfalse : Qtrue;
2191
2183
  }
2192
2184
 
2193
- /*
2194
- * call-seq:
2195
- * conn.cancel() -> String
2196
- *
2197
- * Requests cancellation of the command currently being
2198
- * processed. (Only implemented in PostgreSQL >= 8.0)
2199
- *
2200
- * Returns +nil+ on success, or a string containing the
2201
- * error message if a failure occurs.
2202
- */
2203
2185
  static VALUE
2204
- pgconn_cancel(VALUE self)
2186
+ pgconn_sync_cancel(VALUE self)
2205
2187
  {
2206
- #ifdef HAVE_PQGETCANCEL
2207
2188
  char errbuf[256];
2208
2189
  PGcancel *cancel;
2209
2190
  VALUE retval;
@@ -2211,9 +2192,9 @@ pgconn_cancel(VALUE self)
2211
2192
 
2212
2193
  cancel = PQgetCancel(pg_get_pgconn(self));
2213
2194
  if(cancel == NULL)
2214
- rb_raise(rb_ePGerror,"Invalid connection!");
2195
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2215
2196
 
2216
- ret = gvl_PQcancel(cancel, errbuf, 256);
2197
+ ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2217
2198
  if(ret == 1)
2218
2199
  retval = Qnil;
2219
2200
  else
@@ -2221,9 +2202,6 @@ pgconn_cancel(VALUE self)
2221
2202
 
2222
2203
  PQfreeCancel(cancel);
2223
2204
  return retval;
2224
- #else
2225
- rb_notimplement();
2226
- #endif
2227
2205
  }
2228
2206
 
2229
2207
 
@@ -2237,7 +2215,7 @@ pgconn_cancel(VALUE self)
2237
2215
  static VALUE
2238
2216
  pgconn_notifies(VALUE self)
2239
2217
  {
2240
- PGconn* conn = pg_get_pgconn(self);
2218
+ t_pg_connection *this = pg_get_connection_safe( self );
2241
2219
  PGnotify *notification;
2242
2220
  VALUE hash;
2243
2221
  VALUE sym_relname, sym_be_pid, sym_extra;
@@ -2247,17 +2225,17 @@ pgconn_notifies(VALUE self)
2247
2225
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2248
2226
  sym_extra = ID2SYM(rb_intern("extra"));
2249
2227
 
2250
- notification = gvl_PQnotifies(conn);
2228
+ notification = gvl_PQnotifies(this->pgconn);
2251
2229
  if (notification == NULL) {
2252
2230
  return Qnil;
2253
2231
  }
2254
2232
 
2255
2233
  hash = rb_hash_new();
2256
- relname = rb_tainted_str_new2(notification->relname);
2234
+ relname = rb_str_new2(notification->relname);
2257
2235
  be_pid = INT2NUM(notification->be_pid);
2258
- extra = rb_tainted_str_new2(notification->extra);
2259
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2260
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2236
+ extra = rb_str_new2(notification->extra);
2237
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2238
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2261
2239
 
2262
2240
  rb_hash_aset(hash, sym_relname, relname);
2263
2241
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -2267,96 +2245,63 @@ pgconn_notifies(VALUE self)
2267
2245
  return hash;
2268
2246
  }
2269
2247
 
2270
- /* Win32 + Ruby 1.8 */
2271
- #if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2248
+ #if defined(_WIN32)
2272
2249
 
2273
- /*
2274
- * Duplicate the sockets from libpq and create temporary CRT FDs
2250
+ /* We use a specialized implementation of rb_io_wait() on Windows.
2251
+ * This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
2275
2252
  */
2276
- void create_crt_fd(fd_set *os_set, fd_set *crt_set)
2277
- {
2278
- int i;
2279
- crt_set->fd_count = os_set->fd_count;
2280
- for (i = 0; i < os_set->fd_count; i++) {
2281
- WSAPROTOCOL_INFO wsa_pi;
2282
- /* dupicate the SOCKET */
2283
- int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
2284
- SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
2285
- /* create the CRT fd so ruby can get back to the SOCKET */
2286
- int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
2287
- os_set->fd_array[i] = s;
2288
- crt_set->fd_array[i] = fd;
2289
- }
2290
- }
2291
2253
 
2292
- /*
2293
- * Clean up the CRT FDs from create_crt_fd()
2294
- */
2295
- void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
2296
- {
2297
- int i;
2298
- for (i = 0; i < os_set->fd_count; i++) {
2299
- /* cleanup the CRT fd */
2300
- _close(crt_set->fd_array[i]);
2301
- /* cleanup the duplicated SOCKET */
2302
- closesocket(os_set->fd_array[i]);
2303
- }
2304
- }
2254
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2255
+ #include <ruby/fiber/scheduler.h>
2305
2256
  #endif
2306
2257
 
2307
- /* Win32 + Ruby 1.9+ */
2308
- #if defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2309
- /*
2310
- * On Windows, use platform-specific strategies to wait for the socket
2311
- * instead of rb_thread_select().
2312
- */
2258
+ typedef enum {
2259
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2260
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2261
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2262
+ } pg_rb_io_event_t;
2313
2263
 
2314
2264
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2315
2265
 
2316
- /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2317
- * and does not wait (nor sleep) any time even if timeout is given.
2318
- * Instead use the Winsock events and rb_w32_wait_events(). */
2266
+ static VALUE
2267
+ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
2268
+ rb_io_t *fptr;
2269
+ struct timeval ptimeout;
2319
2270
 
2320
- static void *
2321
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2322
- {
2323
- int sd = PQsocket( conn );
2324
- void *retval;
2325
2271
  struct timeval aborttime={0,0}, currtime, waittime;
2326
2272
  DWORD timeout_milisec = INFINITE;
2327
- DWORD wait_ret;
2328
- WSAEVENT hEvent;
2273
+ HANDLE hEvent = WSACreateEvent();
2329
2274
 
2330
- if ( sd < 0 )
2331
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2332
-
2333
- hEvent = WSACreateEvent();
2275
+ long rb_events = NUM2UINT(events);
2276
+ long w32_events = 0;
2277
+ DWORD wait_ret;
2334
2278
 
2335
- /* Check for connection errors (PQisBusy is true on connection errors) */
2336
- if( PQconsumeInput(conn) == 0 ) {
2337
- WSACloseEvent( hEvent );
2338
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2339
- }
2279
+ GetOpenFile((io), fptr);
2280
+ if( !NIL_P(timeout) ){
2281
+ ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
2282
+ ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
2340
2283
 
2341
- if ( ptimeout ) {
2342
2284
  gettimeofday(&currtime, NULL);
2343
- timeradd(&currtime, ptimeout, &aborttime);
2285
+ timeradd(&currtime, &ptimeout, &aborttime);
2344
2286
  }
2345
2287
 
2346
- while ( !(retval=is_readable(conn)) ) {
2347
- if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2288
+ if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2289
+ if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
2290
+ if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
2291
+
2292
+ for(;;) {
2293
+ if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
2348
2294
  WSACloseEvent( hEvent );
2349
2295
  rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2350
2296
  }
2351
2297
 
2352
- if ( ptimeout ) {
2298
+ if ( !NIL_P(timeout) ) {
2353
2299
  gettimeofday(&currtime, NULL);
2354
2300
  timersub(&aborttime, &currtime, &waittime);
2355
2301
  timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
2356
2302
  }
2357
2303
 
2358
- /* Is the given timeout valid? */
2359
- if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2304
+ if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2360
2305
  /* Wait for the socket to become readable before checking again */
2361
2306
  wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2362
2307
  } else {
@@ -2365,9 +2310,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2365
2310
 
2366
2311
  if ( wait_ret == WAIT_TIMEOUT ) {
2367
2312
  WSACloseEvent( hEvent );
2368
- return NULL;
2313
+ return UINT2NUM(0);
2369
2314
  } else if ( wait_ret == WAIT_OBJECT_0 ) {
2315
+ WSACloseEvent( hEvent );
2370
2316
  /* The event we were waiting for. */
2317
+ return UINT2NUM(rb_events);
2371
2318
  } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2372
2319
  /* This indicates interruption from timer thread, GC, exception
2373
2320
  * from other threads etc... */
@@ -2379,42 +2326,66 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2379
2326
  WSACloseEvent( hEvent );
2380
2327
  rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
2381
2328
  }
2382
-
2383
- /* Check for connection errors (PQisBusy is true on connection errors) */
2384
- if ( PQconsumeInput(conn) == 0 ) {
2385
- WSACloseEvent( hEvent );
2386
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2387
- }
2388
2329
  }
2330
+ }
2389
2331
 
2390
- WSACloseEvent( hEvent );
2391
- return retval;
2332
+ static VALUE
2333
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2334
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2335
+ /* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
2336
+ * Fortunatelly ruby-3.1 offers a C-API for it.
2337
+ */
2338
+ VALUE scheduler = rb_fiber_scheduler_current();
2339
+
2340
+ if (!NIL_P(scheduler)) {
2341
+ return rb_io_wait(io, events, timeout);
2342
+ }
2343
+ #endif
2344
+ return pg_rb_thread_io_wait(io, events, timeout);
2392
2345
  }
2393
2346
 
2347
+ #elif defined(HAVE_RB_IO_WAIT)
2348
+
2349
+ /* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
2350
+ #define pg_rb_io_wait rb_io_wait
2351
+ #define PG_RUBY_IO_READABLE RUBY_IO_READABLE
2352
+ #define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
2353
+ #define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
2354
+
2394
2355
  #else
2356
+ /* For compat with ruby < 3.0 */
2357
+
2358
+ typedef enum {
2359
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2360
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2361
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2362
+ } pg_rb_io_event_t;
2363
+
2364
+ static VALUE
2365
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2366
+ rb_io_t *fptr;
2367
+ struct timeval waittime;
2368
+ int res;
2369
+
2370
+ GetOpenFile((io), fptr);
2371
+ if( !NIL_P(timeout) ){
2372
+ waittime.tv_sec = (time_t)(NUM2DBL(timeout));
2373
+ waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
2374
+ }
2375
+ res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
2395
2376
 
2396
- /* non Win32 or Win32+Ruby-1.8 */
2377
+ return UINT2NUM(res);
2378
+ }
2379
+ #endif
2397
2380
 
2398
2381
  static void *
2399
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2382
+ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2400
2383
  {
2401
- int sd = PQsocket( conn );
2402
- int ret;
2384
+ VALUE ret;
2403
2385
  void *retval;
2404
- rb_fdset_t sd_rset;
2405
2386
  struct timeval aborttime={0,0}, currtime, waittime;
2406
- #ifdef _WIN32
2407
- rb_fdset_t crt_sd_rset;
2408
- #endif
2409
-
2410
- if ( sd < 0 )
2411
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2412
-
2413
- /* Check for connection errors (PQisBusy is true on connection errors) */
2414
- if ( PQconsumeInput(conn) == 0 )
2415
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2416
-
2417
- rb_fd_init( &sd_rset );
2387
+ VALUE wait_timeout = Qnil;
2388
+ PGconn *conn = pg_get_pgconn(self);
2418
2389
 
2419
2390
  if ( ptimeout ) {
2420
2391
  gettimeofday(&currtime, NULL);
@@ -2422,59 +2393,84 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2422
2393
  }
2423
2394
 
2424
2395
  while ( !(retval=is_readable(conn)) ) {
2425
- rb_fd_zero( &sd_rset );
2426
- rb_fd_set( sd, &sd_rset );
2427
-
2428
- #ifdef _WIN32
2429
- /* Ruby's FD_SET is modified on win32 to convert a file descriptor
2430
- * to osfhandle, but we already get a osfhandle from PQsocket().
2431
- * Therefore it's overwritten here. */
2432
- sd_rset.fd_array[0] = sd;
2433
- create_crt_fd(&sd_rset, &crt_sd_rset);
2434
- #endif
2435
-
2436
2396
  if ( ptimeout ) {
2437
2397
  gettimeofday(&currtime, NULL);
2438
2398
  timersub(&aborttime, &currtime, &waittime);
2399
+ wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
2439
2400
  }
2440
2401
 
2441
2402
  /* Is the given timeout valid? */
2442
2403
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2443
- /* Wait for the socket to become readable before checking again */
2444
- ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout ? &waittime : NULL );
2445
- } else {
2446
- ret = 0;
2447
- }
2448
-
2404
+ VALUE socket_io;
2449
2405
 
2450
- #ifdef _WIN32
2451
- cleanup_crt_fd(&sd_rset, &crt_sd_rset);
2452
- #endif
2406
+ /* before we wait for data, make sure everything has been sent */
2407
+ pgconn_async_flush(self);
2408
+ if ((retval=is_readable(conn)))
2409
+ return retval;
2453
2410
 
2454
- if ( ret < 0 ){
2455
- rb_fd_term( &sd_rset );
2456
- rb_sys_fail( "rb_thread_select()" );
2411
+ socket_io = pgconn_socket_io(self);
2412
+ /* Wait for the socket to become readable before checking again */
2413
+ ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2414
+ } else {
2415
+ ret = Qfalse;
2457
2416
  }
2458
2417
 
2459
2418
  /* Return false if the select() timed out */
2460
- if ( ret == 0 ){
2461
- rb_fd_term( &sd_rset );
2419
+ if ( ret == Qfalse ){
2462
2420
  return NULL;
2463
2421
  }
2464
2422
 
2465
2423
  /* Check for connection errors (PQisBusy is true on connection errors) */
2466
2424
  if ( PQconsumeInput(conn) == 0 ){
2467
- rb_fd_term( &sd_rset );
2468
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2425
+ pgconn_close_socket_io(self);
2426
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2469
2427
  }
2470
2428
  }
2471
2429
 
2472
- rb_fd_term( &sd_rset );
2473
2430
  return retval;
2474
2431
  }
2475
2432
 
2433
+ /*
2434
+ * call-seq:
2435
+ * conn.flush() -> Boolean
2436
+ *
2437
+ * Attempts to flush any queued output data to the server.
2438
+ * Returns +true+ if data is successfully flushed, +false+
2439
+ * if not. It can only return +false+ if connection is
2440
+ * in nonblocking mode.
2441
+ * Raises PG::Error if some other failure occurred.
2442
+ */
2443
+ static VALUE
2444
+ pgconn_async_flush(VALUE self)
2445
+ {
2446
+ while( pgconn_sync_flush(self) == Qfalse ){
2447
+ /* wait for the socket to become read- or write-ready */
2448
+ int events;
2449
+ VALUE socket_io = pgconn_socket_io(self);
2450
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2451
+
2452
+ if (events & PG_RUBY_IO_READABLE){
2453
+ pgconn_consume_input(self);
2454
+ }
2455
+ }
2456
+ return Qtrue;
2457
+ }
2458
+
2459
+ static VALUE
2460
+ pgconn_wait_for_flush( VALUE self ){
2461
+ if( !pg_get_connection_safe(self)->flush_data )
2462
+ return Qnil;
2463
+
2464
+ return pgconn_async_flush(self);
2465
+ }
2476
2466
 
2477
- #endif
2467
+ static VALUE
2468
+ pgconn_flush_data_set( VALUE self, VALUE enabled ){
2469
+ t_pg_connection *conn = pg_get_connection(self);
2470
+ rb_check_frozen(self);
2471
+ conn->flush_data = RTEST(enabled);
2472
+ return enabled;
2473
+ }
2478
2474
 
2479
2475
  static void *
2480
2476
  notify_readable(PGconn *conn)
@@ -2484,27 +2480,20 @@ notify_readable(PGconn *conn)
2484
2480
 
2485
2481
  /*
2486
2482
  * call-seq:
2487
- * conn.wait_for_notify( [ timeout ] ) -> String
2488
- * conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
2489
- * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
2483
+ * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
2490
2484
  *
2491
2485
  * Blocks while waiting for notification(s), or until the optional
2492
2486
  * _timeout_ is reached, whichever comes first. _timeout_ is
2493
2487
  * measured in seconds and can be fractional.
2494
2488
  *
2495
- * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
2496
- * event otherwise. If used in block form, passes the name of the
2497
- * NOTIFY +event+ and the generating +pid+ into the block.
2498
- *
2499
- * Under PostgreSQL 9.0 and later, if the notification is sent with
2500
- * the optional +payload+ string, it will be given to the block as the
2501
- * third argument.
2502
- *
2489
+ * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
2490
+ * If used in block form, passes the name of the NOTIFY +event+, the generating
2491
+ * +pid+ and the optional +payload+ string into the block.
2503
2492
  */
2504
2493
  static VALUE
2505
2494
  pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2506
2495
  {
2507
- PGconn *conn = pg_get_pgconn( self );
2496
+ t_pg_connection *this = pg_get_connection_safe( self );
2508
2497
  PGnotify *pnotification;
2509
2498
  struct timeval timeout;
2510
2499
  struct timeval *ptimeout = NULL;
@@ -2520,20 +2509,18 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2520
2509
  ptimeout = &timeout;
2521
2510
  }
2522
2511
 
2523
- pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
2512
+ pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
2524
2513
 
2525
2514
  /* Return nil if the select timed out */
2526
2515
  if ( !pnotification ) return Qnil;
2527
2516
 
2528
- relname = rb_tainted_str_new2( pnotification->relname );
2529
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2517
+ relname = rb_str_new2( pnotification->relname );
2518
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2530
2519
  be_pid = INT2NUM( pnotification->be_pid );
2531
- #ifdef HAVE_ST_NOTIFY_EXTRA
2532
2520
  if ( *pnotification->extra ) {
2533
- extra = rb_tainted_str_new2( pnotification->extra );
2534
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2521
+ extra = rb_str_new2( pnotification->extra );
2522
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2535
2523
  }
2536
- #endif
2537
2524
  PQfreemem( pnotification );
2538
2525
 
2539
2526
  if ( rb_block_given_p() )
@@ -2543,27 +2530,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2543
2530
  }
2544
2531
 
2545
2532
 
2546
- /*
2547
- * call-seq:
2548
- * conn.put_copy_data( buffer [, encoder] ) -> Boolean
2549
- *
2550
- * Transmits _buffer_ as copy data to the server.
2551
- * Returns true if the data was sent, false if it was
2552
- * not sent (false is only possible if the connection
2553
- * is in nonblocking mode, and this command would block).
2554
- *
2555
- * encoder can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
2556
- * This encodes the received data fields from an Array of Strings. Optionally
2557
- * the encoder can type cast the fields form various Ruby types in one step,
2558
- * if PG::TextEncoder::CopyRow#type_map is set accordingly.
2559
- *
2560
- * Raises an exception if an error occurs.
2561
- *
2562
- * See also #copy_data.
2563
- *
2564
- */
2565
2533
  static VALUE
2566
- pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2534
+ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2567
2535
  {
2568
2536
  int ret;
2569
2537
  int len;
@@ -2580,18 +2548,16 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2580
2548
  if( NIL_P(this->encoder_for_put_copy_data) ){
2581
2549
  buffer = value;
2582
2550
  } else {
2583
- p_coder = DATA_PTR( this->encoder_for_put_copy_data );
2551
+ p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
2584
2552
  }
2585
- } else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
2586
- Data_Get_Struct( encoder, t_pg_coder, p_coder );
2587
2553
  } else {
2588
- rb_raise( rb_eTypeError, "wrong encoder type %s (expected some kind of PG::Coder)",
2589
- rb_obj_classname( encoder ) );
2554
+ /* Check argument type and use argument encoder */
2555
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
2590
2556
  }
2591
2557
 
2592
2558
  if( p_coder ){
2593
2559
  t_pg_coder_enc_func enc_func;
2594
- int enc_idx = ENCODING_GET(self);
2560
+ int enc_idx = this->enc_idx;
2595
2561
 
2596
2562
  enc_func = pg_coder_enc_func( p_coder );
2597
2563
  len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
@@ -2609,75 +2575,39 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2609
2575
  Check_Type(buffer, T_STRING);
2610
2576
 
2611
2577
  ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2612
- if(ret == -1) {
2613
- VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2614
- rb_iv_set(error, "@connection", self);
2615
- rb_exc_raise(error);
2616
- }
2578
+ if(ret == -1)
2579
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2580
+
2617
2581
  RB_GC_GUARD(intermediate);
2618
2582
  RB_GC_GUARD(buffer);
2619
2583
 
2620
2584
  return (ret) ? Qtrue : Qfalse;
2621
2585
  }
2622
2586
 
2623
- /*
2624
- * call-seq:
2625
- * conn.put_copy_end( [ error_message ] ) -> Boolean
2626
- *
2627
- * Sends end-of-data indication to the server.
2628
- *
2629
- * _error_message_ is an optional parameter, and if set,
2630
- * forces the COPY command to fail with the string
2631
- * _error_message_.
2632
- *
2633
- * Returns true if the end-of-data was sent, false if it was
2634
- * not sent (false is only possible if the connection
2635
- * is in nonblocking mode, and this command would block).
2636
- */
2637
2587
  static VALUE
2638
- pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2588
+ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2639
2589
  {
2640
2590
  VALUE str;
2641
- VALUE error;
2642
2591
  int ret;
2643
2592
  const char *error_message = NULL;
2644
- PGconn *conn = pg_get_pgconn(self);
2593
+ t_pg_connection *this = pg_get_connection_safe( self );
2645
2594
 
2646
2595
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2647
2596
  error_message = NULL;
2648
2597
  else
2649
- error_message = pg_cstr_enc(str, ENCODING_GET(self));
2598
+ error_message = pg_cstr_enc(str, this->enc_idx);
2599
+
2600
+ ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2601
+ if(ret == -1)
2602
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2650
2603
 
2651
- ret = gvl_PQputCopyEnd(conn, error_message);
2652
- if(ret == -1) {
2653
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2654
- rb_iv_set(error, "@connection", self);
2655
- rb_exc_raise(error);
2656
- }
2657
2604
  return (ret) ? Qtrue : Qfalse;
2658
2605
  }
2659
2606
 
2660
- /*
2661
- * call-seq:
2662
- * conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> String
2663
- *
2664
- * Return a string containing one row of data, +nil+
2665
- * if the copy is done, or +false+ if the call would
2666
- * block (only possible if _async_ is true).
2667
- *
2668
- * decoder can be a PG::Coder derivation (typically PG::TextDecoder::CopyRow).
2669
- * This decodes the received data fields as Array of Strings. Optionally
2670
- * the decoder can type cast the fields to various Ruby types in one step,
2671
- * if PG::TextDecoder::CopyRow#type_map is set accordingly.
2672
- *
2673
- * See also #copy_data.
2674
- *
2675
- */
2676
2607
  static VALUE
2677
- pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2608
+ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2678
2609
  {
2679
2610
  VALUE async_in;
2680
- VALUE error;
2681
2611
  VALUE result;
2682
2612
  int ret;
2683
2613
  char *buffer;
@@ -2689,20 +2619,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2689
2619
 
2690
2620
  if( NIL_P(decoder) ){
2691
2621
  if( !NIL_P(this->decoder_for_get_copy_data) ){
2692
- p_coder = DATA_PTR( this->decoder_for_get_copy_data );
2622
+ p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
2693
2623
  }
2694
- } else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
2695
- Data_Get_Struct( decoder, t_pg_coder, p_coder );
2696
2624
  } else {
2697
- rb_raise( rb_eTypeError, "wrong decoder type %s (expected some kind of PG::Coder)",
2698
- rb_obj_classname( decoder ) );
2625
+ /* Check argument type and use argument decoder */
2626
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
2699
2627
  }
2700
2628
 
2701
2629
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2702
- if(ret == -2) { /* error */
2703
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2704
- rb_iv_set(error, "@connection", self);
2705
- rb_exc_raise(error);
2630
+ if(ret == -2){ /* error */
2631
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2706
2632
  }
2707
2633
  if(ret == -1) { /* No data left */
2708
2634
  return Qnil;
@@ -2713,9 +2639,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2713
2639
 
2714
2640
  if( p_coder ){
2715
2641
  t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
2716
- result = dec_func( p_coder, buffer, ret, 0, 0, ENCODING_GET(self) );
2642
+ result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2717
2643
  } else {
2718
- result = rb_tainted_str_new(buffer, ret);
2644
+ result = rb_str_new(buffer, ret);
2719
2645
  }
2720
2646
 
2721
2647
  PQfreemem(buffer);
@@ -2728,9 +2654,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2728
2654
  *
2729
2655
  * Sets connection's verbosity to _verbosity_ and returns
2730
2656
  * the previous setting. Available settings are:
2657
+ *
2731
2658
  * * PQERRORS_TERSE
2732
2659
  * * PQERRORS_DEFAULT
2733
2660
  * * PQERRORS_VERBOSE
2661
+ * * PQERRORS_SQLSTATE
2662
+ *
2663
+ * Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2664
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
2665
+ *
2666
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
2734
2667
  */
2735
2668
  static VALUE
2736
2669
  pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
@@ -2740,25 +2673,57 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2740
2673
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2741
2674
  }
2742
2675
 
2676
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2743
2677
  /*
2744
2678
  * call-seq:
2745
- * conn.trace( stream ) -> nil
2679
+ * conn.set_error_context_visibility( context_visibility ) -> Integer
2746
2680
  *
2747
- * Enables tracing message passing between backend. The
2748
- * trace message will be written to the stream _stream_,
2749
- * which must implement a method +fileno+ that returns
2750
- * a writable file descriptor.
2681
+ * Sets connection's context display mode to _context_visibility_ and returns
2682
+ * the previous setting. Available settings are:
2683
+ * * PQSHOW_CONTEXT_NEVER
2684
+ * * PQSHOW_CONTEXT_ERRORS
2685
+ * * PQSHOW_CONTEXT_ALWAYS
2686
+ *
2687
+ * This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
2688
+ * The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
2689
+ * In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
2690
+ *
2691
+ * Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2692
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
2693
+ *
2694
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2695
+ *
2696
+ * Available since PostgreSQL-9.6
2751
2697
  */
2752
2698
  static VALUE
2753
- pgconn_trace(VALUE self, VALUE stream)
2699
+ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2754
2700
  {
2755
- VALUE fileno;
2701
+ PGconn *conn = pg_get_pgconn(self);
2702
+ PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2703
+ return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2704
+ }
2705
+ #endif
2706
+
2707
+ /*
2708
+ * call-seq:
2709
+ * conn.trace( stream ) -> nil
2710
+ *
2711
+ * Enables tracing message passing between backend. The
2712
+ * trace message will be written to the stream _stream_,
2713
+ * which must implement a method +fileno+ that returns
2714
+ * a writable file descriptor.
2715
+ */
2716
+ static VALUE
2717
+ pgconn_trace(VALUE self, VALUE stream)
2718
+ {
2719
+ VALUE fileno;
2756
2720
  FILE *new_fp;
2757
2721
  int old_fd, new_fd;
2758
2722
  VALUE new_file;
2759
2723
  t_pg_connection *this = pg_get_connection_safe( self );
2760
2724
 
2761
- if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2725
+ rb_check_frozen(self);
2726
+ if(!rb_respond_to(stream,rb_intern("fileno")))
2762
2727
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2763
2728
 
2764
2729
  fileno = rb_funcall(stream, rb_intern("fileno"), 0);
@@ -2779,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
2779
2744
  rb_raise(rb_eArgError, "stream is not writable");
2780
2745
 
2781
2746
  new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
2782
- this->trace_stream = new_file;
2747
+ RB_OBJ_WRITE(self, &this->trace_stream, new_file);
2783
2748
 
2784
2749
  PQtrace(this->pgconn, new_fp);
2785
2750
  return Qnil;
@@ -2798,7 +2763,7 @@ pgconn_untrace(VALUE self)
2798
2763
 
2799
2764
  PQuntrace(this->pgconn);
2800
2765
  rb_funcall(this->trace_stream, rb_intern("close"), 0);
2801
- this->trace_stream = Qnil;
2766
+ RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
2802
2767
  return Qnil;
2803
2768
  }
2804
2769
 
@@ -2857,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
2857
2822
  VALUE proc, old_proc;
2858
2823
  t_pg_connection *this = pg_get_connection_safe( self );
2859
2824
 
2825
+ rb_check_frozen(self);
2860
2826
  /* If default_notice_receiver is unset, assume that the current
2861
2827
  * notice receiver is the default, and save it to a global variable.
2862
2828
  * This should not be a problem because the default receiver is
2863
2829
  * always the same, so won't vary among connections.
2864
2830
  */
2865
- if(default_notice_receiver == NULL)
2866
- default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
2831
+ if(this->default_notice_receiver == NULL)
2832
+ this->default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
2867
2833
 
2868
2834
  old_proc = this->notice_receiver;
2869
2835
  if( rb_block_given_p() ) {
@@ -2872,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
2872
2838
  } else {
2873
2839
  /* if no block is given, set back to default */
2874
2840
  proc = Qnil;
2875
- PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
2841
+ PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
2876
2842
  }
2877
2843
 
2878
- this->notice_receiver = proc;
2844
+ RB_OBJ_WRITE(self, &this->notice_receiver, proc);
2879
2845
  return old_proc;
2880
2846
  }
2881
2847
 
@@ -2890,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
2890
2856
  VALUE self = (VALUE)arg;
2891
2857
  t_pg_connection *this = pg_get_connection( self );
2892
2858
 
2893
- if (this->notice_receiver != Qnil) {
2894
- VALUE message_str = rb_tainted_str_new2(message);
2895
- PG_ENCODING_SET_NOCHECK( message_str, ENCODING_GET(self) );
2896
- rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2859
+ if (this->notice_processor != Qnil) {
2860
+ VALUE message_str = rb_str_new2(message);
2861
+ PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2862
+ rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
2897
2863
  }
2898
2864
  return;
2899
2865
  }
@@ -2902,7 +2868,7 @@ notice_processor_proxy(void *arg, const char *message)
2902
2868
  * call-seq:
2903
2869
  * conn.set_notice_processor {|message| ... } -> Proc
2904
2870
  *
2905
- * See #set_notice_receiver for the desription of what this and the
2871
+ * See #set_notice_receiver for the description of what this and the
2906
2872
  * notice_processor methods do.
2907
2873
  *
2908
2874
  * This function takes a new block to act as the notice processor and returns
@@ -2917,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
2917
2883
  VALUE proc, old_proc;
2918
2884
  t_pg_connection *this = pg_get_connection_safe( self );
2919
2885
 
2886
+ rb_check_frozen(self);
2920
2887
  /* If default_notice_processor is unset, assume that the current
2921
2888
  * notice processor is the default, and save it to a global variable.
2922
2889
  * This should not be a problem because the default processor is
2923
2890
  * always the same, so won't vary among connections.
2924
2891
  */
2925
- if(default_notice_processor == NULL)
2926
- default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
2892
+ if(this->default_notice_processor == NULL)
2893
+ this->default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
2927
2894
 
2928
- old_proc = this->notice_receiver;
2895
+ old_proc = this->notice_processor;
2929
2896
  if( rb_block_given_p() ) {
2930
2897
  proc = rb_block_proc();
2931
2898
  PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
2932
2899
  } else {
2933
2900
  /* if no block is given, set back to default */
2934
2901
  proc = Qnil;
2935
- PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
2902
+ PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
2936
2903
  }
2937
2904
 
2938
- this->notice_receiver = proc;
2905
+ RB_OBJ_WRITE(self, &this->notice_processor, proc);
2939
2906
  return old_proc;
2940
2907
  }
2941
2908
 
@@ -2950,76 +2917,34 @@ static VALUE
2950
2917
  pgconn_get_client_encoding(VALUE self)
2951
2918
  {
2952
2919
  char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2953
- return rb_tainted_str_new2(encoding);
2920
+ return rb_str_new2(encoding);
2954
2921
  }
2955
2922
 
2956
2923
 
2957
2924
  /*
2958
2925
  * call-seq:
2959
- * conn.set_client_encoding( encoding )
2926
+ * conn.sync_set_client_encoding( encoding )
2960
2927
  *
2961
- * Sets the client encoding to the _encoding_ String.
2928
+ * This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
2929
+ * See #async_exec for the differences between the two API variants.
2930
+ * 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.
2962
2931
  */
2963
2932
  static VALUE
2964
- pgconn_set_client_encoding(VALUE self, VALUE str)
2933
+ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2965
2934
  {
2966
2935
  PGconn *conn = pg_get_pgconn( self );
2967
2936
 
2937
+ rb_check_frozen(self);
2968
2938
  Check_Type(str, T_STRING);
2969
2939
 
2970
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2971
- rb_raise(rb_ePGerror, "invalid encoding name: %s",StringValueCStr(str));
2972
- }
2973
- #ifdef M17N_SUPPORTED
2940
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2941
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2942
+
2974
2943
  pgconn_set_internal_encoding_index( self );
2975
- #endif
2976
2944
 
2977
2945
  return Qnil;
2978
2946
  }
2979
2947
 
2980
- /*
2981
- * call-seq:
2982
- * conn.transaction { |conn| ... } -> result of the block
2983
- *
2984
- * Executes a +BEGIN+ at the start of the block,
2985
- * and a +COMMIT+ at the end of the block, or
2986
- * +ROLLBACK+ if any exception occurs.
2987
- */
2988
- static VALUE
2989
- pgconn_transaction(VALUE self)
2990
- {
2991
- PGconn *conn = pg_get_pgconn(self);
2992
- PGresult *result;
2993
- VALUE rb_pgresult;
2994
- VALUE block_result = Qnil;
2995
- int status;
2996
-
2997
- if (rb_block_given_p()) {
2998
- result = gvl_PQexec(conn, "BEGIN");
2999
- rb_pgresult = pg_new_result(result, self);
3000
- pg_result_check(rb_pgresult);
3001
- block_result = rb_protect(rb_yield, self, &status);
3002
- if(status == 0) {
3003
- result = gvl_PQexec(conn, "COMMIT");
3004
- rb_pgresult = pg_new_result(result, self);
3005
- pg_result_check(rb_pgresult);
3006
- }
3007
- else {
3008
- /* exception occurred, ROLLBACK and re-raise */
3009
- result = gvl_PQexec(conn, "ROLLBACK");
3010
- rb_pgresult = pg_new_result(result, self);
3011
- pg_result_check(rb_pgresult);
3012
- rb_jump_tag(status);
3013
- }
3014
-
3015
- }
3016
- else {
3017
- /* no block supplied? */
3018
- rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
3019
- }
3020
- return block_result;
3021
- }
3022
-
3023
2948
 
3024
2949
  /*
3025
2950
  * call-seq:
@@ -3064,14 +2989,12 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3064
2989
  int enc_idx;
3065
2990
 
3066
2991
  if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3067
- enc_idx = ENCODING_GET( self );
2992
+ enc_idx = pg_get_connection(self)->enc_idx;
3068
2993
  }else{
3069
2994
  enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3070
2995
  }
3071
2996
  pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3072
2997
 
3073
- OBJ_INFECT(ret, str_or_array);
3074
-
3075
2998
  return ret;
3076
2999
  }
3077
3000
 
@@ -3096,14 +3019,8 @@ get_result_readable(PGconn *conn)
3096
3019
  * If +true+ is returned, +conn.is_busy+ will return +false+
3097
3020
  * and +conn.get_result+ will not block.
3098
3021
  */
3099
- static VALUE
3022
+ VALUE
3100
3023
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
3101
- PGconn *conn = pg_get_pgconn( self );
3102
-
3103
- /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
3104
- * and does not wait (nor sleep) any time even if timeout is given.
3105
- * Instead use the Winsock events and rb_w32_wait_events(). */
3106
-
3107
3024
  struct timeval timeout;
3108
3025
  struct timeval *ptimeout = NULL;
3109
3026
  VALUE timeout_in;
@@ -3117,7 +3034,7 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3117
3034
  ptimeout = &timeout;
3118
3035
  }
3119
3036
 
3120
- ret = wait_socket_readable( conn, ptimeout, get_result_readable);
3037
+ ret = wait_socket_readable( self, ptimeout, get_result_readable);
3121
3038
 
3122
3039
  if( !ret )
3123
3040
  return Qfalse;
@@ -3126,6 +3043,42 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3126
3043
  }
3127
3044
 
3128
3045
 
3046
+ /*
3047
+ * call-seq:
3048
+ * conn.sync_get_last_result( ) -> PG::Result
3049
+ *
3050
+ * This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
3051
+ * See #async_exec for the differences between the two API variants.
3052
+ * 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.
3053
+ */
3054
+ static VALUE
3055
+ pgconn_sync_get_last_result(VALUE self)
3056
+ {
3057
+ PGconn *conn = pg_get_pgconn(self);
3058
+ VALUE rb_pgresult = Qnil;
3059
+ PGresult *cur, *prev;
3060
+
3061
+
3062
+ cur = prev = NULL;
3063
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
3064
+ int status;
3065
+
3066
+ if (prev) PQclear(prev);
3067
+ prev = cur;
3068
+
3069
+ status = PQresultStatus(cur);
3070
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3071
+ break;
3072
+ }
3073
+
3074
+ if (prev) {
3075
+ rb_pgresult = pg_new_result( prev, self );
3076
+ pg_result_check(rb_pgresult);
3077
+ }
3078
+
3079
+ return rb_pgresult;
3080
+ }
3081
+
3129
3082
  /*
3130
3083
  * call-seq:
3131
3084
  * conn.get_last_result( ) -> PG::Result
@@ -3136,27 +3089,36 @@ pgconn_block( int argc, VALUE *argv, VALUE self ) {
3136
3089
  * returns the last non-NULL result, or +nil+ if no
3137
3090
  * results are available.
3138
3091
  *
3092
+ * If the last result contains a bad result_status, an
3093
+ * appropriate exception is raised.
3094
+ *
3139
3095
  * This function is similar to #get_result
3140
3096
  * except that it is designed to get one and only
3141
- * one result.
3097
+ * one result and that it checks the result state.
3142
3098
  */
3143
3099
  static VALUE
3144
- pgconn_get_last_result(VALUE self)
3100
+ pgconn_async_get_last_result(VALUE self)
3145
3101
  {
3146
3102
  PGconn *conn = pg_get_pgconn(self);
3147
3103
  VALUE rb_pgresult = Qnil;
3148
3104
  PGresult *cur, *prev;
3149
3105
 
3150
-
3151
3106
  cur = prev = NULL;
3152
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3107
+ for(;;) {
3153
3108
  int status;
3154
3109
 
3110
+ /* wait for input (without blocking) before reading each result */
3111
+ wait_socket_readable(self, NULL, get_result_readable);
3112
+
3113
+ cur = gvl_PQgetResult(conn);
3114
+ if (cur == NULL)
3115
+ break;
3116
+
3155
3117
  if (prev) PQclear(prev);
3156
3118
  prev = cur;
3157
3119
 
3158
3120
  status = PQresultStatus(cur);
3159
- if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
3121
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3160
3122
  break;
3161
3123
  }
3162
3124
 
@@ -3170,25 +3132,132 @@ pgconn_get_last_result(VALUE self)
3170
3132
 
3171
3133
  /*
3172
3134
  * call-seq:
3173
- * conn.async_exec(sql [, params, result_format ] ) -> PG::Result
3174
- * conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
3135
+ * conn.discard_results()
3136
+ *
3137
+ * Silently discard any prior query result that application didn't eat.
3138
+ * This is internally used prior to Connection#exec and sibling methods.
3139
+ * It doesn't raise an exception on connection errors, but returns +false+ instead.
3140
+ *
3141
+ * Returns:
3142
+ * * +nil+ when the connection is already idle
3143
+ * * +true+ when some results have been discarded
3144
+ * * +false+ when a failure occured and the connection was closed
3145
+ *
3146
+ */
3147
+ static VALUE
3148
+ pgconn_discard_results(VALUE self)
3149
+ {
3150
+ PGconn *conn = pg_get_pgconn(self);
3151
+ VALUE socket_io;
3152
+
3153
+ switch( PQtransactionStatus(conn) ) {
3154
+ case PQTRANS_IDLE:
3155
+ case PQTRANS_INTRANS:
3156
+ case PQTRANS_INERROR:
3157
+ return Qnil;
3158
+ default:;
3159
+ }
3160
+
3161
+ socket_io = pgconn_socket_io(self);
3162
+
3163
+ for(;;) {
3164
+ PGresult *cur;
3165
+ int status;
3166
+
3167
+ /* pgconn_block() raises an exception in case of errors.
3168
+ * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3169
+ */
3170
+ while( gvl_PQisBusy(conn) ){
3171
+ int events;
3172
+
3173
+ switch( PQflush(conn) ) {
3174
+ case 1:
3175
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
3176
+ if (events & PG_RUBY_IO_READABLE){
3177
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3178
+ }
3179
+ break;
3180
+ case 0:
3181
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3182
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3183
+ break;
3184
+ default:
3185
+ goto error;
3186
+ }
3187
+ }
3188
+
3189
+ cur = gvl_PQgetResult(conn);
3190
+ if( cur == NULL) break;
3191
+
3192
+ status = PQresultStatus(cur);
3193
+ PQclear(cur);
3194
+ if (status == PGRES_COPY_IN){
3195
+ while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
3196
+ pgconn_async_flush(self);
3197
+ }
3198
+ }
3199
+ if (status == PGRES_COPY_OUT){
3200
+ for(;;) {
3201
+ char *buffer = NULL;
3202
+ int st = gvl_PQgetCopyData(conn, &buffer, 1);
3203
+ if( st == 0 ) {
3204
+ /* would block -> wait for readable data */
3205
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3206
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3207
+ } else if( st > 0 ) {
3208
+ /* some data retrieved -> discard it */
3209
+ PQfreemem(buffer);
3210
+ } else {
3211
+ /* no more data */
3212
+ break;
3213
+ }
3214
+ }
3215
+ }
3216
+ }
3217
+
3218
+ return Qtrue;
3219
+
3220
+ error:
3221
+ pgconn_close_socket_io(self);
3222
+ return Qfalse;
3223
+ }
3224
+
3225
+ /*
3226
+ * call-seq:
3227
+ * conn.exec(sql) -> PG::Result
3228
+ * conn.exec(sql) {|pg_result| block }
3229
+ *
3230
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
3231
+ * On success, it returns a PG::Result instance with all result rows and columns.
3232
+ * On failure, it raises a PG::Error.
3233
+ *
3234
+ * For backward compatibility, if you pass more than one parameter to this method,
3235
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
3236
+ * argument placeholders are used.
3237
+ *
3238
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3239
+ * and the PG::Result object will automatically be cleared when the block terminates.
3240
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3241
+ *
3242
+ * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3243
+ * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3244
+ * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3245
+ * Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
3246
+ * Both methods ensure that other threads can process while waiting for the server to
3247
+ * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3248
+ * This is most notably visible by a delayed reaction to Control+C.
3249
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3175
3250
  *
3176
- * This function has the same behavior as #exec,
3177
- * but is implemented using the asynchronous command
3178
- * processing API of libpq.
3251
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
3179
3252
  */
3180
3253
  static VALUE
3181
3254
  pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3182
3255
  {
3183
3256
  VALUE rb_pgresult = Qnil;
3184
3257
 
3185
- /* remove any remaining results from the queue */
3186
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3187
- pgconn_get_last_result( self );
3188
-
3258
+ pgconn_discard_results( self );
3189
3259
  pgconn_send_query( argc, argv, self );
3190
- pgconn_block( 0, NULL, self );
3191
- rb_pgresult = pgconn_get_last_result( self );
3260
+ rb_pgresult = pgconn_async_get_last_result( self );
3192
3261
 
3193
3262
  if ( rb_block_given_p() ) {
3194
3263
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3197,15 +3266,225 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3197
3266
  }
3198
3267
 
3199
3268
 
3200
- #ifdef HAVE_PQSSLATTRIBUTE
3201
- /* Since PostgreSQL-9.5: */
3269
+ /*
3270
+ * call-seq:
3271
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3272
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3273
+ *
3274
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
3275
+ * for parameters.
3276
+ *
3277
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
3278
+ *
3279
+ * +params+ is an array of the bind parameters for the SQL query.
3280
+ * Each element of the +params+ array may be either:
3281
+ * a hash of the form:
3282
+ * {:value => String (value of bind parameter)
3283
+ * :type => Integer (oid of type of bind parameter)
3284
+ * :format => Integer (0 for text, 1 for binary)
3285
+ * }
3286
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3287
+ * { :value => <string value>, :type => 0, :format => 0 }
3288
+ *
3289
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3290
+ * inside the SQL query. The 0th element of the +params+ array is bound
3291
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3292
+ *
3293
+ * If the types are not specified, they will be inferred by PostgreSQL.
3294
+ * Instead of specifying type oids, it's recommended to simply add
3295
+ * explicit casts in the query to ensure that the right type is used.
3296
+ *
3297
+ * For example: "SELECT $1::int"
3298
+ *
3299
+ * The optional +result_format+ should be 0 for text results, 1
3300
+ * for binary.
3301
+ *
3302
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3303
+ * This will type cast the params from various Ruby types before transmission
3304
+ * based on the encoders defined by the type map. When a type encoder is used
3305
+ * the format and oid of a given bind parameter are retrieved from the encoder
3306
+ * instead out of the hash form described above.
3307
+ *
3308
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3309
+ * and the PG::Result object will automatically be cleared when the block terminates.
3310
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3311
+ *
3312
+ * 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.
3313
+ * Unlike #exec, #exec_params allows at most one SQL command in the given string.
3314
+ * (There can be semicolons in it, but not more than one nonempty command.)
3315
+ * This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
3316
+ *
3317
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
3318
+ */
3319
+ static VALUE
3320
+ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3321
+ {
3322
+ VALUE rb_pgresult = Qnil;
3323
+
3324
+ pgconn_discard_results( self );
3325
+ /* If called with no or nil parameters, use PQsendQuery for compatibility */
3326
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
3327
+ pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
3328
+ pgconn_send_query( argc, argv, self );
3329
+ } else {
3330
+ pgconn_send_query_params( argc, argv, self );
3331
+ }
3332
+ rb_pgresult = pgconn_async_get_last_result( self );
3333
+
3334
+ if ( rb_block_given_p() ) {
3335
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3336
+ }
3337
+ return rb_pgresult;
3338
+ }
3339
+
3340
+
3341
+ /*
3342
+ * call-seq:
3343
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3344
+ *
3345
+ * Prepares statement _sql_ with name _name_ to be executed later.
3346
+ * Returns a PG::Result instance on success.
3347
+ * On failure, it raises a PG::Error.
3348
+ *
3349
+ * +param_types+ is an optional parameter to specify the Oids of the
3350
+ * types of the parameters.
3351
+ *
3352
+ * If the types are not specified, they will be inferred by PostgreSQL.
3353
+ * Instead of specifying type oids, it's recommended to simply add
3354
+ * explicit casts in the query to ensure that the right type is used.
3355
+ *
3356
+ * For example: "SELECT $1::int"
3357
+ *
3358
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3359
+ * inside the SQL query.
3360
+ *
3361
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
3362
+ */
3363
+ static VALUE
3364
+ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3365
+ {
3366
+ VALUE rb_pgresult = Qnil;
3367
+
3368
+ pgconn_discard_results( self );
3369
+ pgconn_send_prepare( argc, argv, self );
3370
+ rb_pgresult = pgconn_async_get_last_result( self );
3371
+
3372
+ if ( rb_block_given_p() ) {
3373
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3374
+ }
3375
+ return rb_pgresult;
3376
+ }
3377
+
3378
+
3379
+ /*
3380
+ * call-seq:
3381
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3382
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3383
+ *
3384
+ * Execute prepared named statement specified by _statement_name_.
3385
+ * Returns a PG::Result instance on success.
3386
+ * On failure, it raises a PG::Error.
3387
+ *
3388
+ * +params+ is an array of the optional bind parameters for the
3389
+ * SQL query. Each element of the +params+ array may be either:
3390
+ * a hash of the form:
3391
+ * {:value => String (value of bind parameter)
3392
+ * :format => Integer (0 for text, 1 for binary)
3393
+ * }
3394
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3395
+ * { :value => <string value>, :format => 0 }
3396
+ *
3397
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3398
+ * inside the SQL query. The 0th element of the +params+ array is bound
3399
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3400
+ *
3401
+ * The optional +result_format+ should be 0 for text results, 1
3402
+ * for binary.
3403
+ *
3404
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3405
+ * This will type cast the params from various Ruby types before transmission
3406
+ * based on the encoders defined by the type map. When a type encoder is used
3407
+ * the format and oid of a given bind parameter are retrieved from the encoder
3408
+ * instead out of the hash form described above.
3409
+ *
3410
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3411
+ * and the PG::Result object will automatically be cleared when the block terminates.
3412
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
3413
+ *
3414
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
3415
+ */
3416
+ static VALUE
3417
+ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3418
+ {
3419
+ VALUE rb_pgresult = Qnil;
3420
+
3421
+ pgconn_discard_results( self );
3422
+ pgconn_send_query_prepared( argc, argv, self );
3423
+ rb_pgresult = pgconn_async_get_last_result( self );
3424
+
3425
+ if ( rb_block_given_p() ) {
3426
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3427
+ }
3428
+ return rb_pgresult;
3429
+ }
3430
+
3431
+
3432
+ /*
3433
+ * call-seq:
3434
+ * conn.describe_portal( portal_name ) -> PG::Result
3435
+ *
3436
+ * Retrieve information about the portal _portal_name_.
3437
+ *
3438
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
3439
+ */
3440
+ static VALUE
3441
+ pgconn_async_describe_portal(VALUE self, VALUE portal)
3442
+ {
3443
+ VALUE rb_pgresult = Qnil;
3444
+
3445
+ pgconn_discard_results( self );
3446
+ pgconn_send_describe_portal( self, portal );
3447
+ rb_pgresult = pgconn_async_get_last_result( self );
3448
+
3449
+ if ( rb_block_given_p() ) {
3450
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3451
+ }
3452
+ return rb_pgresult;
3453
+ }
3454
+
3455
+
3456
+ /*
3457
+ * call-seq:
3458
+ * conn.describe_prepared( statement_name ) -> PG::Result
3459
+ *
3460
+ * Retrieve information about the prepared statement _statement_name_.
3461
+ *
3462
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
3463
+ */
3464
+ static VALUE
3465
+ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3466
+ {
3467
+ VALUE rb_pgresult = Qnil;
3202
3468
 
3469
+ pgconn_discard_results( self );
3470
+ pgconn_send_describe_prepared( self, stmt_name );
3471
+ rb_pgresult = pgconn_async_get_last_result( self );
3472
+
3473
+ if ( rb_block_given_p() ) {
3474
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3475
+ }
3476
+ return rb_pgresult;
3477
+ }
3478
+
3479
+
3480
+ #ifdef HAVE_PQSSLATTRIBUTE
3203
3481
  /*
3204
3482
  * call-seq:
3205
3483
  * conn.ssl_in_use? -> Boolean
3206
3484
  *
3207
- * Returns +true+ if the connection uses SSL, +false+ if not.
3485
+ * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3208
3486
  *
3487
+ * Available since PostgreSQL-9.5
3209
3488
  */
3210
3489
  static VALUE
3211
3490
  pgconn_ssl_in_use(VALUE self)
@@ -3237,7 +3516,9 @@ pgconn_ssl_in_use(VALUE self)
3237
3516
  * 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".
3238
3517
  *
3239
3518
  *
3240
- * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3519
+ * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3520
+ *
3521
+ * Available since PostgreSQL-9.5
3241
3522
  */
3242
3523
  static VALUE
3243
3524
  pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
@@ -3256,6 +3537,7 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
3256
3537
  *
3257
3538
  * See also #ssl_attribute
3258
3539
  *
3540
+ * Available since PostgreSQL-9.5
3259
3541
  */
3260
3542
  static VALUE
3261
3543
  pgconn_ssl_attribute_names(VALUE self)
@@ -3274,10 +3556,134 @@ pgconn_ssl_attribute_names(VALUE self)
3274
3556
  #endif
3275
3557
 
3276
3558
 
3559
+ #ifdef HAVE_PQENTERPIPELINEMODE
3560
+ /*
3561
+ * call-seq:
3562
+ * conn.pipeline_status -> Integer
3563
+ *
3564
+ * Returns the current pipeline mode status of the libpq connection.
3565
+ *
3566
+ * PQpipelineStatus can return one of the following values:
3567
+ *
3568
+ * * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
3569
+ * * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
3570
+ * * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
3571
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
3572
+ *
3573
+ * Available since PostgreSQL-14
3574
+ */
3575
+ static VALUE
3576
+ pgconn_pipeline_status(VALUE self)
3577
+ {
3578
+ int res = PQpipelineStatus(pg_get_pgconn(self));
3579
+ return INT2FIX(res);
3580
+ }
3581
+
3582
+
3583
+ /*
3584
+ * call-seq:
3585
+ * conn.enter_pipeline_mode -> nil
3586
+ *
3587
+ * Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
3588
+ *
3589
+ * 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.
3590
+ * This function does not actually send anything to the server, it just changes the libpq connection state.
3591
+ *
3592
+ * Available since PostgreSQL-14
3593
+ */
3594
+ static VALUE
3595
+ pgconn_enter_pipeline_mode(VALUE self)
3596
+ {
3597
+ PGconn *conn = pg_get_pgconn(self);
3598
+ int res = PQenterPipelineMode(conn);
3599
+ if( res != 1 )
3600
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3601
+
3602
+ return Qnil;
3603
+ }
3604
+
3605
+ /*
3606
+ * call-seq:
3607
+ * conn.exit_pipeline_mode -> nil
3608
+ *
3609
+ * Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
3610
+ *
3611
+ * Takes no action if not in pipeline mode.
3612
+ * 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.
3613
+ *
3614
+ * Available since PostgreSQL-14
3615
+ */
3616
+ static VALUE
3617
+ pgconn_exit_pipeline_mode(VALUE self)
3618
+ {
3619
+ PGconn *conn = pg_get_pgconn(self);
3620
+ int res = PQexitPipelineMode(conn);
3621
+ if( res != 1 )
3622
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3623
+
3624
+ return Qnil;
3625
+ }
3626
+
3627
+
3628
+ /*
3629
+ * call-seq:
3630
+ * conn.pipeline_sync -> nil
3631
+ *
3632
+ * Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
3633
+ * This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
3634
+ *
3635
+ * Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
3636
+ *
3637
+ * Available since PostgreSQL-14
3638
+ */
3639
+ static VALUE
3640
+ pgconn_pipeline_sync(VALUE self)
3641
+ {
3642
+ PGconn *conn = pg_get_pgconn(self);
3643
+ int res = PQpipelineSync(conn);
3644
+ if( res != 1 )
3645
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3646
+
3647
+ return Qnil;
3648
+ }
3649
+
3650
+ /*
3651
+ * call-seq:
3652
+ * conn.pipeline_sync -> nil
3653
+ *
3654
+ * Sends a request for the server to flush its output buffer.
3655
+ *
3656
+ * 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.
3657
+ * This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
3658
+ * Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
3659
+ *
3660
+ * Available since PostgreSQL-14
3661
+ */
3662
+ static VALUE
3663
+ pgconn_send_flush_request(VALUE self)
3664
+ {
3665
+ PGconn *conn = pg_get_pgconn(self);
3666
+ int res = PQsendFlushRequest(conn);
3667
+ if( res != 1 )
3668
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3669
+
3670
+ return Qnil;
3671
+ }
3672
+
3673
+ #endif
3674
+
3277
3675
  /**************************************************************************
3278
3676
  * LARGE OBJECT SUPPORT
3279
3677
  **************************************************************************/
3280
3678
 
3679
+ #define BLOCKING_BEGIN(conn) do { \
3680
+ int old_nonblocking = PQisnonblocking(conn); \
3681
+ PQsetnonblocking(conn, 0);
3682
+
3683
+ #define BLOCKING_END(th) \
3684
+ PQsetnonblocking(conn, old_nonblocking); \
3685
+ } while(0);
3686
+
3281
3687
  /*
3282
3688
  * call-seq:
3283
3689
  * conn.lo_creat( [mode] ) -> Integer
@@ -3298,9 +3704,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3298
3704
  else
3299
3705
  mode = NUM2INT(nmode);
3300
3706
 
3301
- lo_oid = lo_creat(conn, mode);
3707
+ BLOCKING_BEGIN(conn)
3708
+ lo_oid = lo_creat(conn, mode);
3709
+ BLOCKING_END(conn)
3710
+
3302
3711
  if (lo_oid == 0)
3303
- rb_raise(rb_ePGerror, "lo_creat failed");
3712
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3304
3713
 
3305
3714
  return UINT2NUM(lo_oid);
3306
3715
  }
@@ -3321,7 +3730,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3321
3730
 
3322
3731
  ret = lo_create(conn, lo_oid);
3323
3732
  if (ret == InvalidOid)
3324
- rb_raise(rb_ePGerror, "lo_create failed");
3733
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3325
3734
 
3326
3735
  return UINT2NUM(ret);
3327
3736
  }
@@ -3343,9 +3752,12 @@ pgconn_loimport(VALUE self, VALUE filename)
3343
3752
 
3344
3753
  Check_Type(filename, T_STRING);
3345
3754
 
3346
- lo_oid = lo_import(conn, StringValueCStr(filename));
3755
+ BLOCKING_BEGIN(conn)
3756
+ lo_oid = lo_import(conn, StringValueCStr(filename));
3757
+ BLOCKING_END(conn)
3758
+
3347
3759
  if (lo_oid == 0) {
3348
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3760
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3349
3761
  }
3350
3762
  return UINT2NUM(lo_oid);
3351
3763
  }
@@ -3361,12 +3773,17 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3361
3773
  {
3362
3774
  PGconn *conn = pg_get_pgconn(self);
3363
3775
  Oid oid;
3776
+ int ret;
3364
3777
  Check_Type(filename, T_STRING);
3365
3778
 
3366
3779
  oid = NUM2UINT(lo_oid);
3367
3780
 
3368
- if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3369
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3781
+ BLOCKING_BEGIN(conn)
3782
+ ret = lo_export(conn, oid, StringValueCStr(filename));
3783
+ BLOCKING_END(conn)
3784
+
3785
+ if (ret < 0) {
3786
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3370
3787
  }
3371
3788
  return Qnil;
3372
3789
  }
@@ -3396,8 +3813,12 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3396
3813
  else
3397
3814
  mode = NUM2INT(nmode);
3398
3815
 
3399
- if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3400
- rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3816
+ BLOCKING_BEGIN(conn)
3817
+ fd = lo_open(conn, lo_oid, mode);
3818
+ BLOCKING_END(conn)
3819
+
3820
+ if(fd < 0) {
3821
+ pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3401
3822
  }
3402
3823
  return INT2FIX(fd);
3403
3824
  }
@@ -3419,11 +3840,15 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3419
3840
  Check_Type(buffer, T_STRING);
3420
3841
 
3421
3842
  if( RSTRING_LEN(buffer) < 0) {
3422
- rb_raise(rb_ePGerror, "write buffer zero string");
3843
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3423
3844
  }
3424
- if((n = lo_write(conn, fd, StringValuePtr(buffer),
3425
- RSTRING_LEN(buffer))) < 0) {
3426
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3845
+ BLOCKING_BEGIN(conn)
3846
+ n = lo_write(conn, fd, StringValuePtr(buffer),
3847
+ RSTRING_LEN(buffer));
3848
+ BLOCKING_END(conn)
3849
+
3850
+ if(n < 0) {
3851
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3427
3852
  }
3428
3853
 
3429
3854
  return INT2FIX(n);
@@ -3446,23 +3871,24 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3446
3871
  VALUE str;
3447
3872
  char *buffer;
3448
3873
 
3449
- buffer = ALLOC_N(char, len);
3450
- if(buffer == NULL)
3451
- rb_raise(rb_eNoMemError, "ALLOC failed!");
3874
+ if (len < 0)
3875
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3452
3876
 
3453
- if (len < 0){
3454
- rb_raise(rb_ePGerror,"nagative length %d given", len);
3455
- }
3877
+ buffer = ALLOC_N(char, len);
3456
3878
 
3457
- if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3458
- rb_raise(rb_ePGerror, "lo_read failed");
3879
+ BLOCKING_BEGIN(conn)
3880
+ ret = lo_read(conn, lo_desc, buffer, len);
3881
+ BLOCKING_END(conn)
3882
+
3883
+ if(ret < 0)
3884
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3459
3885
 
3460
3886
  if(ret == 0) {
3461
3887
  xfree(buffer);
3462
3888
  return Qnil;
3463
3889
  }
3464
3890
 
3465
- str = rb_tainted_str_new(buffer, ret);
3891
+ str = rb_str_new(buffer, ret);
3466
3892
  xfree(buffer);
3467
3893
 
3468
3894
  return str;
@@ -3484,8 +3910,12 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3484
3910
  int lo_desc = NUM2INT(in_lo_desc);
3485
3911
  int ret;
3486
3912
 
3487
- if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3488
- rb_raise(rb_ePGerror, "lo_lseek failed");
3913
+ BLOCKING_BEGIN(conn)
3914
+ ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
3915
+ BLOCKING_END(conn)
3916
+
3917
+ if(ret < 0) {
3918
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3489
3919
  }
3490
3920
 
3491
3921
  return INT2FIX(ret);
@@ -3504,8 +3934,12 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3504
3934
  PGconn *conn = pg_get_pgconn(self);
3505
3935
  int lo_desc = NUM2INT(in_lo_desc);
3506
3936
 
3507
- if((position = lo_tell(conn, lo_desc)) < 0)
3508
- rb_raise(rb_ePGerror,"lo_tell failed");
3937
+ BLOCKING_BEGIN(conn)
3938
+ position = lo_tell(conn, lo_desc);
3939
+ BLOCKING_END(conn)
3940
+
3941
+ if(position < 0)
3942
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3509
3943
 
3510
3944
  return INT2FIX(position);
3511
3945
  }
@@ -3522,9 +3956,14 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3522
3956
  PGconn *conn = pg_get_pgconn(self);
3523
3957
  int lo_desc = NUM2INT(in_lo_desc);
3524
3958
  size_t len = NUM2INT(in_len);
3959
+ int ret;
3960
+
3961
+ BLOCKING_BEGIN(conn)
3962
+ ret = lo_truncate(conn,lo_desc,len);
3963
+ BLOCKING_END(conn)
3525
3964
 
3526
- if(lo_truncate(conn,lo_desc,len) < 0)
3527
- rb_raise(rb_ePGerror,"lo_truncate failed");
3965
+ if(ret < 0)
3966
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3528
3967
 
3529
3968
  return Qnil;
3530
3969
  }
@@ -3540,9 +3979,14 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3540
3979
  {
3541
3980
  PGconn *conn = pg_get_pgconn(self);
3542
3981
  int lo_desc = NUM2INT(in_lo_desc);
3982
+ int ret;
3983
+
3984
+ BLOCKING_BEGIN(conn)
3985
+ ret = lo_close(conn,lo_desc);
3986
+ BLOCKING_END(conn)
3543
3987
 
3544
- if(lo_close(conn,lo_desc) < 0)
3545
- rb_raise(rb_ePGerror,"lo_close failed");
3988
+ if(ret < 0)
3989
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3546
3990
 
3547
3991
  return Qnil;
3548
3992
  }
@@ -3558,22 +4002,28 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3558
4002
  {
3559
4003
  PGconn *conn = pg_get_pgconn(self);
3560
4004
  Oid oid = NUM2UINT(in_oid);
4005
+ int ret;
4006
+
4007
+ BLOCKING_BEGIN(conn)
4008
+ ret = lo_unlink(conn,oid);
4009
+ BLOCKING_END(conn)
3561
4010
 
3562
- if(lo_unlink(conn,oid) < 0)
3563
- rb_raise(rb_ePGerror,"lo_unlink failed");
4011
+ if(ret < 0)
4012
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3564
4013
 
3565
4014
  return Qnil;
3566
4015
  }
3567
4016
 
3568
4017
 
3569
- #ifdef M17N_SUPPORTED
3570
-
3571
- void
4018
+ static void
3572
4019
  pgconn_set_internal_encoding_index( VALUE self )
3573
4020
  {
3574
- PGconn *conn = pg_get_pgconn(self);
3575
- rb_encoding *enc = pg_conn_enc_get( conn );
3576
- PG_ENCODING_SET_NOCHECK( self, rb_enc_to_index(enc));
4021
+ int enc_idx;
4022
+ t_pg_connection *this = pg_get_connection_safe( self );
4023
+ rb_encoding *enc = pg_conn_enc_get( this->pgconn );
4024
+ enc_idx = rb_enc_to_index(enc);
4025
+ if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
4026
+ this->enc_idx = enc_idx;
3577
4027
  }
3578
4028
 
3579
4029
  /*
@@ -3616,13 +4066,13 @@ static VALUE pgconn_external_encoding(VALUE self);
3616
4066
  static VALUE
3617
4067
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3618
4068
  {
3619
- VALUE enc_inspect;
4069
+ rb_check_frozen(self);
3620
4070
  if (NIL_P(enc)) {
3621
- pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
4071
+ pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3622
4072
  return enc;
3623
4073
  }
3624
4074
  else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
3625
- pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
4075
+ pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3626
4076
  return enc;
3627
4077
  }
3628
4078
  else {
@@ -3637,11 +4087,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3637
4087
  pgconn_set_internal_encoding_index( self );
3638
4088
  return enc;
3639
4089
  }
3640
-
3641
- enc_inspect = rb_inspect(enc);
3642
- rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
3643
-
3644
- return Qnil;
3645
4090
  }
3646
4091
 
3647
4092
 
@@ -3660,42 +4105,56 @@ pgconn_external_encoding(VALUE self)
3660
4105
  rb_encoding *enc = NULL;
3661
4106
  const char *pg_encname = NULL;
3662
4107
 
3663
- /* Use cached value if found */
3664
- if ( RTEST(this->external_encoding) ) return this->external_encoding;
3665
-
3666
4108
  pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
3667
4109
  enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
3668
- this->external_encoding = rb_enc_from_encoding( enc );
3669
-
3670
- return this->external_encoding;
4110
+ return rb_enc_from_encoding( enc );
3671
4111
  }
3672
4112
 
4113
+ /*
4114
+ * call-seq:
4115
+ * conn.set_client_encoding( encoding )
4116
+ *
4117
+ * Sets the client encoding to the _encoding_ String.
4118
+ */
4119
+ static VALUE
4120
+ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4121
+ {
4122
+ VALUE query_format, query;
4123
+
4124
+ rb_check_frozen(self);
4125
+ Check_Type(encname, T_STRING);
4126
+ query_format = rb_str_new_cstr("set client_encoding to '%s'");
4127
+ query = rb_funcall(query_format, rb_intern("%"), 1, encname);
4128
+
4129
+ pgconn_async_exec(1, &query, self);
4130
+ pgconn_set_internal_encoding_index( self );
4131
+
4132
+ return Qnil;
4133
+ }
3673
4134
 
3674
4135
  static VALUE
3675
4136
  pgconn_set_client_encoding_async1( VALUE args )
3676
4137
  {
3677
4138
  VALUE self = ((VALUE*)args)[0];
3678
4139
  VALUE encname = ((VALUE*)args)[1];
3679
- VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3680
- VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3681
-
3682
- pgconn_async_exec(1, &query, self);
4140
+ pgconn_async_set_client_encoding(self, encname);
3683
4141
  return 0;
3684
4142
  }
3685
4143
 
3686
4144
 
3687
4145
  static VALUE
3688
- pgconn_set_client_encoding_async2( VALUE arg )
4146
+ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3689
4147
  {
3690
4148
  UNUSED(arg);
4149
+ UNUSED(ex);
3691
4150
  return 1;
3692
4151
  }
3693
4152
 
3694
4153
 
3695
4154
  static VALUE
3696
- pgconn_set_client_encoding_async( VALUE self, const char *encname )
4155
+ pgconn_set_client_encoding_async( VALUE self, VALUE encname )
3697
4156
  {
3698
- VALUE args[] = { self, rb_str_new_cstr(encname) };
4157
+ VALUE args[] = { self, encname };
3699
4158
  return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3700
4159
  }
3701
4160
 
@@ -3715,12 +4174,12 @@ pgconn_set_default_encoding( VALUE self )
3715
4174
  rb_encoding *enc;
3716
4175
  const char *encname;
3717
4176
 
4177
+ rb_check_frozen(self);
3718
4178
  if (( enc = rb_default_internal_encoding() )) {
3719
4179
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3720
- if ( pgconn_set_client_encoding_async(self, encname) != 0 )
3721
- rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
4180
+ if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
4181
+ rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
3722
4182
  encname, PQerrorMessage(conn) );
3723
- pgconn_set_internal_encoding_index( self );
3724
4183
  return rb_enc_from_encoding( enc );
3725
4184
  } else {
3726
4185
  pgconn_set_internal_encoding_index( self );
@@ -3729,8 +4188,6 @@ pgconn_set_default_encoding( VALUE self )
3729
4188
  }
3730
4189
 
3731
4190
 
3732
- #endif /* M17N_SUPPORTED */
3733
-
3734
4191
  /*
3735
4192
  * call-seq:
3736
4193
  * res.type_map_for_queries = typemap
@@ -3744,13 +4201,14 @@ static VALUE
3744
4201
  pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
3745
4202
  {
3746
4203
  t_pg_connection *this = pg_get_connection( self );
4204
+ t_typemap *tm;
4205
+ UNUSED(tm);
3747
4206
 
3748
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3749
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3750
- rb_obj_classname( typemap ) );
3751
- }
3752
- Check_Type(typemap, T_DATA);
3753
- this->type_map_for_queries = typemap;
4207
+ rb_check_frozen(self);
4208
+ /* Check type of method param */
4209
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4210
+
4211
+ RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
3754
4212
 
3755
4213
  return typemap;
3756
4214
  }
@@ -3784,13 +4242,12 @@ static VALUE
3784
4242
  pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
3785
4243
  {
3786
4244
  t_pg_connection *this = pg_get_connection( self );
4245
+ t_typemap *tm;
4246
+ UNUSED(tm);
3787
4247
 
3788
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3789
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3790
- rb_obj_classname( typemap ) );
3791
- }
3792
- Check_Type(typemap, T_DATA);
3793
- this->type_map_for_results = typemap;
4248
+ rb_check_frozen(self);
4249
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4250
+ RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
3794
4251
 
3795
4252
  return typemap;
3796
4253
  }
@@ -3824,20 +4281,20 @@ pgconn_type_map_for_results_get(VALUE self)
3824
4281
  *
3825
4282
  */
3826
4283
  static VALUE
3827
- pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
4284
+ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
3828
4285
  {
3829
4286
  t_pg_connection *this = pg_get_connection( self );
3830
4287
 
3831
- if( typemap != Qnil ){
3832
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
3833
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
3834
- rb_obj_classname( typemap ) );
3835
- }
3836
- Check_Type(typemap, T_DATA);
4288
+ rb_check_frozen(self);
4289
+ if( encoder != Qnil ){
4290
+ t_pg_coder *co;
4291
+ UNUSED(co);
4292
+ /* Check argument type */
4293
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
3837
4294
  }
3838
- this->encoder_for_put_copy_data = typemap;
4295
+ RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
3839
4296
 
3840
- return typemap;
4297
+ return encoder;
3841
4298
  }
3842
4299
 
3843
4300
  /*
@@ -3873,20 +4330,20 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
3873
4330
  *
3874
4331
  */
3875
4332
  static VALUE
3876
- pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE typemap)
4333
+ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
3877
4334
  {
3878
4335
  t_pg_connection *this = pg_get_connection( self );
3879
4336
 
3880
- if( typemap != Qnil ){
3881
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
3882
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
3883
- rb_obj_classname( typemap ) );
3884
- }
3885
- Check_Type(typemap, T_DATA);
4337
+ rb_check_frozen(self);
4338
+ if( decoder != Qnil ){
4339
+ t_pg_coder *co;
4340
+ UNUSED(co);
4341
+ /* Check argument type */
4342
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
3886
4343
  }
3887
- this->decoder_for_get_copy_data = typemap;
4344
+ RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
3888
4345
 
3889
- return typemap;
4346
+ return decoder;
3890
4347
  }
3891
4348
 
3892
4349
  /*
@@ -3909,28 +4366,83 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
3909
4366
  return this->decoder_for_get_copy_data;
3910
4367
  }
3911
4368
 
4369
+ /*
4370
+ * call-seq:
4371
+ * conn.field_name_type = Symbol
4372
+ *
4373
+ * Set default type of field names of results retrieved by this connection.
4374
+ * It can be set to one of:
4375
+ * * +:string+ to use String based field names
4376
+ * * +:symbol+ to use Symbol based field names
4377
+ *
4378
+ * The default is +:string+ .
4379
+ *
4380
+ * Settings the type of field names affects only future results.
4381
+ *
4382
+ * See further description at PG::Result#field_name_type=
4383
+ *
4384
+ */
4385
+ static VALUE
4386
+ pgconn_field_name_type_set(VALUE self, VALUE sym)
4387
+ {
4388
+ t_pg_connection *this = pg_get_connection( self );
4389
+
4390
+ rb_check_frozen(self);
4391
+ this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4392
+ if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4393
+ else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4394
+ else if ( sym == sym_string );
4395
+ else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4396
+
4397
+ return sym;
4398
+ }
4399
+
4400
+ /*
4401
+ * call-seq:
4402
+ * conn.field_name_type -> Symbol
4403
+ *
4404
+ * Get type of field names.
4405
+ *
4406
+ * See description at #field_name_type=
4407
+ */
4408
+ static VALUE
4409
+ pgconn_field_name_type_get(VALUE self)
4410
+ {
4411
+ t_pg_connection *this = pg_get_connection( self );
4412
+
4413
+ if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4414
+ return sym_symbol;
4415
+ } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4416
+ return sym_static_symbol;
4417
+ } else {
4418
+ return sym_string;
4419
+ }
4420
+ }
4421
+
3912
4422
 
3913
4423
  /*
3914
4424
  * Document-class: PG::Connection
3915
4425
  */
3916
4426
  void
3917
- init_pg_connection()
4427
+ init_pg_connection(void)
3918
4428
  {
3919
4429
  s_id_encode = rb_intern("encode");
4430
+ s_id_autoclose_set = rb_intern("autoclose=");
3920
4431
  sym_type = ID2SYM(rb_intern("type"));
3921
4432
  sym_format = ID2SYM(rb_intern("format"));
3922
4433
  sym_value = ID2SYM(rb_intern("value"));
4434
+ sym_string = ID2SYM(rb_intern("string"));
4435
+ sym_symbol = ID2SYM(rb_intern("symbol"));
4436
+ sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
3923
4437
 
3924
4438
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4439
+ /* Help rdoc to known the Constants module */
4440
+ /* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
3925
4441
  rb_include_module(rb_cPGconn, rb_mPGconstants);
3926
4442
 
3927
4443
  /****** PG::Connection CLASS METHODS ******/
3928
4444
  rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
3929
4445
 
3930
- SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
3931
- SINGLETON_ALIAS(rb_cPGconn, "open", "new");
3932
- SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
3933
- SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
3934
4446
  rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3935
4447
  SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
3936
4448
  rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
@@ -3939,16 +4451,15 @@ init_pg_connection()
3939
4451
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
3940
4452
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
3941
4453
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
3942
- #ifdef HAVE_PQPING
3943
- rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
3944
- #endif
4454
+ rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
4455
+ rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4456
+ rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
3945
4457
 
3946
4458
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
3947
- rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
3948
4459
  rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
3949
4460
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
3950
4461
  rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
3951
- rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
4462
+ rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
3952
4463
  rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
3953
4464
  rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
3954
4465
  rb_define_alias(rb_cPGconn, "close", "finish");
@@ -3958,11 +4469,12 @@ init_pg_connection()
3958
4469
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
3959
4470
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
3960
4471
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4472
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
4473
+ rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
4474
+ #endif
3961
4475
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
3962
4476
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
3963
- #ifdef HAVE_PQCONNINFO
3964
4477
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
3965
- #endif
3966
4478
  rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
3967
4479
  rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
3968
4480
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
@@ -3971,64 +4483,78 @@ init_pg_connection()
3971
4483
  rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
3972
4484
  rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
3973
4485
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
3974
- #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
3975
4486
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
3976
- #endif
3977
4487
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4488
+ rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
3978
4489
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
3979
4490
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
3980
4491
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
3981
4492
 
3982
4493
  /****** PG::Connection INSTANCE METHODS: Command Execution ******/
3983
- rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
3984
- rb_define_alias(rb_cPGconn, "query", "exec");
3985
- rb_define_method(rb_cPGconn, "exec_params", pgconn_exec_params, -1);
3986
- rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
3987
- rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
3988
- rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
3989
- rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
4494
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
4495
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
4496
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
4497
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4498
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4499
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4500
+
4501
+ rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4502
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
4503
+ rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
4504
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4505
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4506
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4507
+
4508
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
4509
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4510
+ rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
4511
+ rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
4512
+ rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4513
+ rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4514
+ rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4515
+
3990
4516
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
3991
4517
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3992
4518
  rb_define_alias(rb_cPGconn, "escape", "escape_string");
3993
- #ifdef HAVE_PQESCAPELITERAL
3994
4519
  rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
3995
- #endif
3996
- #ifdef HAVE_PQESCAPEIDENTIFIER
3997
4520
  rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
3998
- #endif
3999
4521
  rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
4000
4522
  rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
4001
- #ifdef HAVE_PQSETSINGLEROWMODE
4002
4523
  rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
4003
- #endif
4004
4524
 
4005
4525
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
4006
4526
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
4527
+ rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
4007
4528
  rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
4008
4529
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
4009
4530
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
4010
4531
  rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
4011
- rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
4532
+ rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
4012
4533
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4013
4534
  rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
4014
- rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
4015
- rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
4016
- rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
4017
- rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
4535
+ rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
4536
+ rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
4537
+ rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
4538
+ rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
4539
+ rb_define_alias(rb_cPGconn, "async_flush", "flush");
4540
+ rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4018
4541
 
4019
4542
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4020
- rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
4543
+ rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4021
4544
 
4022
4545
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4023
4546
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
4024
4547
 
4025
4548
  /****** PG::Connection INSTANCE METHODS: COPY ******/
4026
- rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, -1);
4027
- rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
4028
- rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
4549
+ rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
4550
+ rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
4551
+ rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
4029
4552
 
4030
4553
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4031
4554
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4555
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4556
+ rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4557
+ #endif
4032
4558
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
4033
4559
  rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
4034
4560
 
@@ -4038,16 +4564,21 @@ init_pg_connection()
4038
4564
 
4039
4565
  /****** PG::Connection INSTANCE METHODS: Other ******/
4040
4566
  rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
4041
- rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
4567
+ rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
4568
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
4569
+ rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
4042
4570
  rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
4043
- rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
4044
4571
  rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
4572
+ rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
4045
4573
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
4046
4574
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
4047
4575
  rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4048
- rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
4049
- rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4050
- rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
4576
+ rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4577
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4578
+ rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4579
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
4580
+ rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4581
+ #endif
4051
4582
 
4052
4583
  #ifdef HAVE_PQSSLATTRIBUTE
4053
4584
  rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
@@ -4055,6 +4586,14 @@ init_pg_connection()
4055
4586
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4056
4587
  #endif
4057
4588
 
4589
+ #ifdef HAVE_PQENTERPIPELINEMODE
4590
+ rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4591
+ rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4592
+ rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4593
+ rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
4594
+ rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4595
+ #endif
4596
+
4058
4597
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
4059
4598
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
4060
4599
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
@@ -4083,12 +4622,10 @@ init_pg_connection()
4083
4622
  rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
4084
4623
  rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
4085
4624
 
4086
- #ifdef M17N_SUPPORTED
4087
4625
  rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
4088
4626
  rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
4089
4627
  rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
4090
4628
  rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
4091
- #endif /* M17N_SUPPORTED */
4092
4629
 
4093
4630
  rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
4094
4631
  rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
@@ -4098,5 +4635,7 @@ init_pg_connection()
4098
4635
  rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
4099
4636
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
4100
4637
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
4101
- }
4102
4638
 
4639
+ rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
4640
+ rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
4641
+ }