pg 0.18.1 → 1.5.6

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