pg 0.18.2 → 1.4.5

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