pg 0.21.0 → 1.3.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (117) hide show
  1. checksums.yaml +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 +130 -0
  7. data/.gitignore +13 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/Gemfile +14 -0
  15. data/History.rdoc +291 -4
  16. data/Manifest.txt +8 -4
  17. data/README-Windows.rdoc +4 -4
  18. data/README.ja.rdoc +1 -2
  19. data/README.rdoc +62 -16
  20. data/Rakefile +32 -142
  21. data/Rakefile.cross +69 -71
  22. data/certs/ged.pem +24 -0
  23. data/certs/larskanis-2022.pem +26 -0
  24. data/ext/errorcodes.def +84 -0
  25. data/ext/errorcodes.rb +1 -1
  26. data/ext/errorcodes.txt +23 -2
  27. data/ext/extconf.rb +109 -52
  28. data/ext/gvl_wrappers.c +8 -0
  29. data/ext/gvl_wrappers.h +40 -33
  30. data/ext/pg.c +211 -146
  31. data/ext/pg.h +85 -95
  32. data/ext/pg_binary_decoder.c +82 -15
  33. data/ext/pg_binary_encoder.c +13 -12
  34. data/ext/pg_coder.c +145 -30
  35. data/ext/pg_connection.c +1349 -929
  36. data/ext/pg_copy_coder.c +60 -23
  37. data/ext/pg_record_coder.c +519 -0
  38. data/ext/pg_result.c +613 -207
  39. data/ext/pg_text_decoder.c +606 -40
  40. data/ext/pg_text_encoder.c +190 -59
  41. data/ext/pg_tuple.c +575 -0
  42. data/ext/pg_type_map.c +42 -9
  43. data/ext/pg_type_map_all_strings.c +19 -5
  44. data/ext/pg_type_map_by_class.c +54 -24
  45. data/ext/pg_type_map_by_column.c +73 -34
  46. data/ext/pg_type_map_by_mri_type.c +48 -19
  47. data/ext/pg_type_map_by_oid.c +55 -25
  48. data/ext/pg_type_map_in_ruby.c +51 -20
  49. data/ext/{util.c → pg_util.c} +12 -12
  50. data/ext/{util.h → pg_util.h} +2 -2
  51. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  52. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  53. data/lib/pg/basic_type_map_for_results.rb +81 -0
  54. data/lib/pg/basic_type_registry.rb +296 -0
  55. data/lib/pg/binary_decoder.rb +23 -0
  56. data/lib/pg/coder.rb +24 -3
  57. data/lib/pg/connection.rb +600 -46
  58. data/lib/pg/constants.rb +2 -1
  59. data/lib/pg/exceptions.rb +2 -1
  60. data/lib/pg/result.rb +14 -2
  61. data/lib/pg/text_decoder.rb +21 -26
  62. data/lib/pg/text_encoder.rb +32 -8
  63. data/lib/pg/tuple.rb +30 -0
  64. data/lib/pg/type_map_by_column.rb +3 -2
  65. data/lib/pg/version.rb +4 -0
  66. data/lib/pg.rb +51 -38
  67. data/misc/openssl-pg-segfault.rb +31 -0
  68. data/misc/postgres/History.txt +9 -0
  69. data/misc/postgres/Manifest.txt +5 -0
  70. data/misc/postgres/README.txt +21 -0
  71. data/misc/postgres/Rakefile +21 -0
  72. data/misc/postgres/lib/postgres.rb +16 -0
  73. data/misc/ruby-pg/History.txt +9 -0
  74. data/misc/ruby-pg/Manifest.txt +5 -0
  75. data/misc/ruby-pg/README.txt +21 -0
  76. data/misc/ruby-pg/Rakefile +21 -0
  77. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  78. data/pg.gemspec +32 -0
  79. data/sample/array_insert.rb +20 -0
  80. data/sample/async_api.rb +106 -0
  81. data/sample/async_copyto.rb +39 -0
  82. data/sample/async_mixed.rb +56 -0
  83. data/sample/check_conn.rb +21 -0
  84. data/sample/copydata.rb +71 -0
  85. data/sample/copyfrom.rb +81 -0
  86. data/sample/copyto.rb +19 -0
  87. data/sample/cursor.rb +21 -0
  88. data/sample/disk_usage_report.rb +177 -0
  89. data/sample/issue-119.rb +94 -0
  90. data/sample/losample.rb +69 -0
  91. data/sample/minimal-testcase.rb +17 -0
  92. data/sample/notify_wait.rb +72 -0
  93. data/sample/pg_statistics.rb +285 -0
  94. data/sample/replication_monitor.rb +222 -0
  95. data/sample/test_binary_values.rb +33 -0
  96. data/sample/wal_shipper.rb +434 -0
  97. data/sample/warehouse_partitions.rb +311 -0
  98. data.tar.gz.sig +0 -0
  99. metadata +96 -229
  100. metadata.gz.sig +0 -0
  101. data/ChangeLog +0 -6595
  102. data/lib/pg/basic_type_mapping.rb +0 -426
  103. data/lib/pg/deprecated_constants.rb +0 -21
  104. data/spec/data/expected_trace.out +0 -26
  105. data/spec/data/random_binary_data +0 -0
  106. data/spec/helpers.rb +0 -352
  107. data/spec/pg/basic_type_mapping_spec.rb +0 -305
  108. data/spec/pg/connection_spec.rb +0 -1676
  109. data/spec/pg/result_spec.rb +0 -456
  110. data/spec/pg/type_map_by_class_spec.rb +0 -138
  111. data/spec/pg/type_map_by_column_spec.rb +0 -222
  112. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  113. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  114. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  115. data/spec/pg/type_map_spec.rb +0 -22
  116. data/spec/pg/type_spec.rb +0 -777
  117. data/spec/pg_spec.rb +0 -50
data/ext/pg_connection.c CHANGED
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * pg_connection.c - PG::Connection class extension
3
- * $Id: pg_connection.c,v 2e17f315848e 2017/01/14 20:05:06 lars $
3
+ * $Id$
4
4
  *
5
5
  */
6
6
 
@@ -12,25 +12,18 @@
12
12
 
13
13
  VALUE rb_cPGconn;
14
14
  static ID s_id_encode;
15
+ static ID s_id_autoclose_set;
15
16
  static VALUE sym_type, sym_format, sym_value;
17
+ static VALUE sym_symbol, sym_string, sym_static_symbol;
16
18
 
17
19
  static PQnoticeReceiver default_notice_receiver = NULL;
18
20
  static PQnoticeProcessor default_notice_processor = NULL;
19
21
 
20
22
  static VALUE pgconn_finish( VALUE );
21
- #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;
34
27
 
35
28
  /*
36
29
  * Global functions
@@ -43,7 +36,7 @@ t_pg_connection *
43
36
  pg_get_connection( VALUE self )
44
37
  {
45
38
  t_pg_connection *this;
46
- Data_Get_Struct( self, t_pg_connection, this);
39
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
47
40
 
48
41
  return this;
49
42
  }
@@ -56,7 +49,7 @@ static t_pg_connection *
56
49
  pg_get_connection_safe( VALUE self )
57
50
  {
58
51
  t_pg_connection *this;
59
- Data_Get_Struct( self, t_pg_connection, this);
52
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
60
53
 
61
54
  if ( !this->pgconn )
62
55
  rb_raise( rb_eConnectionBad, "connection is closed" );
@@ -75,7 +68,7 @@ PGconn *
75
68
  pg_get_pgconn( VALUE self )
76
69
  {
77
70
  t_pg_connection *this;
78
- Data_Get_Struct( self, t_pg_connection, this);
71
+ TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
79
72
 
80
73
  if ( !this->pgconn )
81
74
  rb_raise( rb_eConnectionBad, "connection is closed" );
@@ -95,9 +88,8 @@ pgconn_close_socket_io( VALUE self )
95
88
  VALUE socket_io = this->socket_io;
96
89
 
97
90
  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) ){
91
+ #if defined(_WIN32)
92
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
101
93
  rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
102
94
  }
103
95
  #endif
@@ -156,17 +148,31 @@ static const char *pg_cstr_enc(VALUE str, int enc_idx){
156
148
  * GC Mark function
157
149
  */
158
150
  static void
159
- pgconn_gc_mark( t_pg_connection *this )
151
+ pgconn_gc_mark( void *_this )
152
+ {
153
+ t_pg_connection *this = (t_pg_connection *)_this;
154
+ rb_gc_mark_movable( this->socket_io );
155
+ rb_gc_mark_movable( this->notice_receiver );
156
+ rb_gc_mark_movable( this->notice_processor );
157
+ rb_gc_mark_movable( this->type_map_for_queries );
158
+ rb_gc_mark_movable( this->type_map_for_results );
159
+ rb_gc_mark_movable( this->trace_stream );
160
+ rb_gc_mark_movable( this->encoder_for_put_copy_data );
161
+ rb_gc_mark_movable( this->decoder_for_get_copy_data );
162
+ }
163
+
164
+ static void
165
+ pgconn_gc_compact( void *_this )
160
166
  {
161
- rb_gc_mark( this->socket_io );
162
- rb_gc_mark( this->notice_receiver );
163
- rb_gc_mark( this->notice_processor );
164
- rb_gc_mark( this->type_map_for_queries );
165
- rb_gc_mark( this->type_map_for_results );
166
- rb_gc_mark( this->trace_stream );
167
- rb_gc_mark( this->external_encoding );
168
- rb_gc_mark( this->encoder_for_put_copy_data );
169
- rb_gc_mark( this->decoder_for_get_copy_data );
167
+ t_pg_connection *this = (t_pg_connection *)_this;
168
+ pg_gc_location( this->socket_io );
169
+ pg_gc_location( this->notice_receiver );
170
+ pg_gc_location( this->notice_processor );
171
+ pg_gc_location( this->type_map_for_queries );
172
+ pg_gc_location( this->type_map_for_results );
173
+ pg_gc_location( this->trace_stream );
174
+ pg_gc_location( this->encoder_for_put_copy_data );
175
+ pg_gc_location( this->decoder_for_get_copy_data );
170
176
  }
171
177
 
172
178
 
@@ -174,14 +180,45 @@ pgconn_gc_mark( t_pg_connection *this )
174
180
  * GC Free function
175
181
  */
176
182
  static void
177
- pgconn_gc_free( t_pg_connection *this )
183
+ pgconn_gc_free( void *_this )
178
184
  {
185
+ t_pg_connection *this = (t_pg_connection *)_this;
186
+ #if defined(_WIN32)
187
+ if ( RTEST(this->socket_io) ) {
188
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
189
+ rb_warn("pg: Could not unwrap win32 socket handle by garbage collector");
190
+ }
191
+ }
192
+ #endif
179
193
  if (this->pgconn != NULL)
180
194
  PQfinish( this->pgconn );
181
195
 
182
196
  xfree(this);
183
197
  }
184
198
 
199
+ /*
200
+ * Object Size function
201
+ */
202
+ static size_t
203
+ pgconn_memsize( const void *_this )
204
+ {
205
+ const t_pg_connection *this = (const t_pg_connection *)_this;
206
+ return sizeof(*this);
207
+ }
208
+
209
+ static const rb_data_type_t pg_connection_type = {
210
+ "PG::Connection",
211
+ {
212
+ pgconn_gc_mark,
213
+ pgconn_gc_free,
214
+ pgconn_memsize,
215
+ pg_compact_callback(pgconn_gc_compact),
216
+ },
217
+ 0,
218
+ 0,
219
+ 0,
220
+ };
221
+
185
222
 
186
223
  /**************************************************************************
187
224
  * Class Methods
@@ -197,7 +234,7 @@ static VALUE
197
234
  pgconn_s_allocate( VALUE klass )
198
235
  {
199
236
  t_pg_connection *this;
200
- VALUE self = Data_Make_Struct( klass, t_pg_connection, pgconn_gc_mark, pgconn_gc_free, this );
237
+ VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
201
238
 
202
239
  this->pgconn = NULL;
203
240
  this->socket_io = Qnil;
@@ -208,75 +245,17 @@ pgconn_s_allocate( VALUE klass )
208
245
  this->encoder_for_put_copy_data = Qnil;
209
246
  this->decoder_for_get_copy_data = Qnil;
210
247
  this->trace_stream = Qnil;
211
- this->external_encoding = Qnil;
212
248
 
213
249
  return self;
214
250
  }
215
251
 
216
-
217
- /*
218
- * Document-method: new
219
- *
220
- * call-seq:
221
- * PG::Connection.new -> conn
222
- * PG::Connection.new(connection_hash) -> conn
223
- * PG::Connection.new(connection_string) -> conn
224
- * PG::Connection.new(host, port, options, tty, dbname, user, password) -> conn
225
- *
226
- * Create a connection to the specified server.
227
- *
228
- * [+host+]
229
- * server hostname
230
- * [+hostaddr+]
231
- * server address (avoids hostname lookup, overrides +host+)
232
- * [+port+]
233
- * server port number
234
- * [+dbname+]
235
- * connecting database name
236
- * [+user+]
237
- * login user name
238
- * [+password+]
239
- * login password
240
- * [+connect_timeout+]
241
- * maximum time to wait for connection to succeed
242
- * [+options+]
243
- * backend options
244
- * [+tty+]
245
- * (ignored in newer versions of PostgreSQL)
246
- * [+sslmode+]
247
- * (disable|allow|prefer|require)
248
- * [+krbsrvname+]
249
- * kerberos service name
250
- * [+gsslib+]
251
- * GSS library to use for GSSAPI authentication
252
- * [+service+]
253
- * service name to use for additional parameters
254
- *
255
- * Examples:
256
- *
257
- * # Connect using all defaults
258
- * PG::Connection.new
259
- *
260
- * # As a Hash
261
- * PG::Connection.new( :dbname => 'test', :port => 5432 )
262
- *
263
- * # As a String
264
- * PG::Connection.new( "dbname=test port=5432" )
265
- *
266
- * # As an Array
267
- * PG::Connection.new( nil, 5432, nil, nil, 'test', nil, nil )
268
- *
269
- * If the Ruby default internal encoding is set (i.e., Encoding.default_internal != nil), the
270
- * connection will have its +client_encoding+ set accordingly.
271
- *
272
- * Raises a PG::Error if the connection fails.
273
- */
274
252
  static VALUE
275
- pgconn_init(int argc, VALUE *argv, VALUE self)
253
+ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
276
254
  {
277
255
  t_pg_connection *this;
278
256
  VALUE conninfo;
279
257
  VALUE error;
258
+ VALUE self = pgconn_s_allocate( klass );
280
259
 
281
260
  this = pg_get_connection( self );
282
261
  conninfo = rb_funcall2( rb_cPGconn, rb_intern("parse_connect_args"), argc, argv );
@@ -291,9 +270,7 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
291
270
  rb_exc_raise(error);
292
271
  }
293
272
 
294
- #ifdef M17N_SUPPORTED
295
273
  pgconn_set_default_encoding( self );
296
- #endif
297
274
 
298
275
  if (rb_block_given_p()) {
299
276
  return rb_ensure(rb_yield, self, pgconn_finish, self);
@@ -307,14 +284,16 @@ pgconn_init(int argc, VALUE *argv, VALUE self)
307
284
  * PG::Connection.connect_start(connection_string) -> conn
308
285
  * PG::Connection.connect_start(host, port, options, tty, dbname, login, password) -> conn
309
286
  *
310
- * This is an asynchronous version of PG::Connection.connect().
287
+ * This is an asynchronous version of PG::Connection.new.
311
288
  *
312
289
  * Use #connect_poll to poll the status of the connection.
313
290
  *
314
291
  * NOTE: this does *not* set the connection's +client_encoding+ for you if
315
- * Encoding.default_internal is set. To set it after the connection is established,
292
+ * +Encoding.default_internal+ is set. To set it after the connection is established,
316
293
  * call #internal_encoding=. You can also set it automatically by setting
317
- * ENV['PGCLIENTENCODING'], or include the 'options' connection parameter.
294
+ * <code>ENV['PGCLIENTENCODING']</code>, or include the 'options' connection parameter.
295
+ *
296
+ * See also the 'sample' directory of this gem and the corresponding {libpq functions}[https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-PQCONNECTSTARTPARAMS].
318
297
  *
319
298
  */
320
299
  static VALUE
@@ -349,37 +328,17 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
349
328
  return rb_conn;
350
329
  }
351
330
 
352
- #ifdef HAVE_PQPING
353
- /*
354
- * call-seq:
355
- * PG::Connection.ping(connection_hash) -> Integer
356
- * PG::Connection.ping(connection_string) -> Integer
357
- * PG::Connection.ping(host, port, options, tty, dbname, login, password) -> Integer
358
- *
359
- * Check server status.
360
- *
361
- * Returns one of:
362
- * [+PQPING_OK+]
363
- * server is accepting connections
364
- * [+PQPING_REJECT+]
365
- * server is alive but rejecting connections
366
- * [+PQPING_NO_RESPONSE+]
367
- * could not establish connection
368
- * [+PQPING_NO_ATTEMPT+]
369
- * connection not attempted (bad params)
370
- */
371
331
  static VALUE
372
- pgconn_s_ping( int argc, VALUE *argv, VALUE klass )
332
+ pgconn_s_sync_ping( int argc, VALUE *argv, VALUE klass )
373
333
  {
374
334
  PGPing ping;
375
335
  VALUE conninfo;
376
336
 
377
337
  conninfo = rb_funcall2( klass, rb_intern("parse_connect_args"), argc, argv );
378
- ping = PQping( StringValueCStr(conninfo) );
338
+ ping = gvl_PQping( StringValueCStr(conninfo) );
379
339
 
380
340
  return INT2FIX((int)ping);
381
341
  }
382
- #endif
383
342
 
384
343
 
385
344
  /*
@@ -418,16 +377,40 @@ pgconn_s_conndefaults(VALUE self)
418
377
  }
419
378
 
420
379
 
380
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
381
+ static VALUE
382
+ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
383
+ {
384
+ char *encrypted = NULL;
385
+ VALUE rval = Qnil;
386
+ VALUE password, username, algorithm;
387
+ PGconn *conn = pg_get_pgconn(self);
388
+
389
+ rb_scan_args( argc, argv, "21", &password, &username, &algorithm );
390
+
391
+ Check_Type(password, T_STRING);
392
+ Check_Type(username, T_STRING);
393
+
394
+ encrypted = gvl_PQencryptPasswordConn(conn, StringValueCStr(password), StringValueCStr(username), RTEST(algorithm) ? StringValueCStr(algorithm) : NULL);
395
+ if ( encrypted ) {
396
+ rval = rb_str_new2( encrypted );
397
+ PQfreemem( encrypted );
398
+ } else {
399
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
400
+ }
401
+
402
+ return rval;
403
+ }
404
+ #endif
405
+
406
+
421
407
  /*
422
408
  * call-seq:
423
409
  * PG::Connection.encrypt_password( password, username ) -> String
424
410
  *
425
- * This function is intended to be used by client applications that
426
- * send commands like: +ALTER USER joe PASSWORD 'pwd'+.
427
- * The arguments are the cleartext password, and the SQL name
428
- * of the user it is for.
411
+ * This is an older, deprecated version of #encrypt_password.
412
+ * The difference is that this function always uses +md5+ as the encryption algorithm.
429
413
  *
430
- * Return value is the encrypted password.
431
414
  */
432
415
  static VALUE
433
416
  pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
@@ -444,9 +427,6 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
444
427
  rval = rb_str_new2( encrypted );
445
428
  PQfreemem( encrypted );
446
429
 
447
- OBJ_INFECT( rval, password );
448
- OBJ_INFECT( rval, username );
449
-
450
430
  return rval;
451
431
  }
452
432
 
@@ -494,6 +474,11 @@ pgconn_connect_poll(VALUE self)
494
474
  {
495
475
  PostgresPollingStatusType status;
496
476
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
477
+
478
+ if ( status == PGRES_POLLING_FAILED ) {
479
+ pgconn_close_socket_io(self);
480
+ }
481
+
497
482
  return INT2FIX((int)status);
498
483
  }
499
484
 
@@ -530,15 +515,8 @@ pgconn_finished_p( VALUE self )
530
515
  }
531
516
 
532
517
 
533
- /*
534
- * call-seq:
535
- * conn.reset()
536
- *
537
- * Resets the backend connection. This method closes the
538
- * backend connection and tries to re-connect.
539
- */
540
518
  static VALUE
541
- pgconn_reset( VALUE self )
519
+ pgconn_sync_reset( VALUE self )
542
520
  {
543
521
  pgconn_close_socket_io( self );
544
522
  gvl_PQreset( pg_get_pgconn(self) );
@@ -577,6 +555,11 @@ pgconn_reset_poll(VALUE self)
577
555
  {
578
556
  PostgresPollingStatusType status;
579
557
  status = gvl_PQresetPoll(pg_get_pgconn(self));
558
+
559
+ if ( status == PGRES_POLLING_FAILED ) {
560
+ pgconn_close_socket_io(self);
561
+ }
562
+
580
563
  return INT2FIX((int)status);
581
564
  }
582
565
 
@@ -592,7 +575,7 @@ pgconn_db(VALUE self)
592
575
  {
593
576
  char *db = PQdb(pg_get_pgconn(self));
594
577
  if (!db) return Qnil;
595
- return rb_tainted_str_new2(db);
578
+ return rb_str_new2(db);
596
579
  }
597
580
 
598
581
  /*
@@ -606,21 +589,21 @@ pgconn_user(VALUE self)
606
589
  {
607
590
  char *user = PQuser(pg_get_pgconn(self));
608
591
  if (!user) return Qnil;
609
- return rb_tainted_str_new2(user);
592
+ return rb_str_new2(user);
610
593
  }
611
594
 
612
595
  /*
613
596
  * call-seq:
614
597
  * conn.pass()
615
598
  *
616
- * Returns the authenticated user name.
599
+ * Returns the authenticated password.
617
600
  */
618
601
  static VALUE
619
602
  pgconn_pass(VALUE self)
620
603
  {
621
604
  char *user = PQpass(pg_get_pgconn(self));
622
605
  if (!user) return Qnil;
623
- return rb_tainted_str_new2(user);
606
+ return rb_str_new2(user);
624
607
  }
625
608
 
626
609
  /*
@@ -634,7 +617,7 @@ pgconn_host(VALUE self)
634
617
  {
635
618
  char *host = PQhost(pg_get_pgconn(self));
636
619
  if (!host) return Qnil;
637
- return rb_tainted_str_new2(host);
620
+ return rb_str_new2(host);
638
621
  }
639
622
 
640
623
  /*
@@ -647,21 +630,19 @@ static VALUE
647
630
  pgconn_port(VALUE self)
648
631
  {
649
632
  char* port = PQport(pg_get_pgconn(self));
650
- return INT2NUM(atol(port));
633
+ return INT2NUM(atoi(port));
651
634
  }
652
635
 
653
636
  /*
654
637
  * call-seq:
655
638
  * conn.tty()
656
639
  *
657
- * Returns the connected pgtty. (Obsolete)
640
+ * Obsolete function.
658
641
  */
659
642
  static VALUE
660
643
  pgconn_tty(VALUE self)
661
644
  {
662
- char *tty = PQtty(pg_get_pgconn(self));
663
- if (!tty) return Qnil;
664
- return rb_tainted_str_new2(tty);
645
+ return rb_str_new2("");
665
646
  }
666
647
 
667
648
  /*
@@ -675,17 +656,17 @@ pgconn_options(VALUE self)
675
656
  {
676
657
  char *options = PQoptions(pg_get_pgconn(self));
677
658
  if (!options) return Qnil;
678
- return rb_tainted_str_new2(options);
659
+ return rb_str_new2(options);
679
660
  }
680
661
 
681
662
 
682
- #ifdef HAVE_PQCONNINFO
683
663
  /*
684
664
  * call-seq:
685
665
  * conn.conninfo -> hash
686
666
  *
687
667
  * Returns the connection options used by a live connection.
688
668
  *
669
+ * Available since PostgreSQL-9.3
689
670
  */
690
671
  static VALUE
691
672
  pgconn_conninfo( VALUE self )
@@ -698,14 +679,17 @@ pgconn_conninfo( VALUE self )
698
679
 
699
680
  return array;
700
681
  }
701
- #endif
702
682
 
703
683
 
704
684
  /*
705
685
  * call-seq:
706
686
  * conn.status()
707
687
  *
708
- * Returns status of connection : CONNECTION_OK or CONNECTION_BAD
688
+ * Returns the status of the connection, which is one:
689
+ * PG::Constants::CONNECTION_OK
690
+ * PG::Constants::CONNECTION_BAD
691
+ *
692
+ * ... and other constants of kind PG::Constants::CONNECTION_*
709
693
  */
710
694
  static VALUE
711
695
  pgconn_status(VALUE self)
@@ -755,7 +739,7 @@ pgconn_parameter_status(VALUE self, VALUE param_name)
755
739
  if(ret == NULL)
756
740
  return Qnil;
757
741
  else
758
- return rb_tainted_str_new2(ret);
742
+ return rb_str_new2(ret);
759
743
  }
760
744
 
761
745
  /*
@@ -793,20 +777,25 @@ pgconn_server_version(VALUE self)
793
777
  * call-seq:
794
778
  * conn.error_message -> String
795
779
  *
796
- * Returns the error message about connection.
780
+ * Returns the error message most recently generated by an operation on the connection.
781
+ *
782
+ * Nearly all libpq functions will set a message for conn.error_message if they fail.
783
+ * Note that by libpq convention, a nonempty error_message result can consist of multiple lines, and will include a trailing newline.
797
784
  */
798
785
  static VALUE
799
786
  pgconn_error_message(VALUE self)
800
787
  {
801
788
  char *error = PQerrorMessage(pg_get_pgconn(self));
802
789
  if (!error) return Qnil;
803
- return rb_tainted_str_new2(error);
790
+ return rb_str_new2(error);
804
791
  }
805
792
 
806
793
  /*
807
794
  * call-seq:
808
795
  * conn.socket() -> Integer
809
796
  *
797
+ * This method is deprecated. Please use the more portable method #socket_io .
798
+ *
810
799
  * Returns the socket's file descriptor for this connection.
811
800
  * <tt>IO.for_fd()</tt> can be used to build a proper IO object to the socket.
812
801
  * If you do so, you will likely also want to set <tt>autoclose=false</tt>
@@ -815,42 +804,39 @@ pgconn_error_message(VALUE self)
815
804
  * creates an IO that's associated with the connection object itself,
816
805
  * and so won't go out of scope until the connection does.
817
806
  *
818
- * *Note:* On Windows the file descriptor is not really usable,
807
+ * *Note:* On Windows the file descriptor is not usable,
819
808
  * since it can not be used to build a Ruby IO object.
820
809
  */
821
810
  static VALUE
822
811
  pgconn_socket(VALUE self)
823
812
  {
824
813
  int sd;
814
+ pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
815
+
825
816
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
826
817
  rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
827
818
  return INT2NUM(sd);
828
819
  }
829
820
 
830
-
831
- #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
832
-
833
821
  /*
834
822
  * call-seq:
835
823
  * conn.socket_io() -> IO
836
824
  *
837
- * Fetch a memoized IO object created from the Connection's underlying socket.
825
+ * Fetch a memorized IO object created from the Connection's underlying socket.
838
826
  * This object can be used for IO.select to wait for events while running
839
827
  * asynchronous API calls.
840
828
  *
841
829
  * Using this instead of #socket avoids the problem of the underlying connection
842
830
  * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
843
- * goes out of scope.
844
- *
845
- * This method can also be used on Windows but requires Ruby-2.0+.
831
+ * goes out of scope. In contrast to #socket, it also works on Windows.
846
832
  */
847
833
  static VALUE
848
834
  pgconn_socket_io(VALUE self)
849
835
  {
850
836
  int sd;
851
837
  int ruby_sd;
852
- ID id_autoclose = rb_intern("autoclose=");
853
838
  t_pg_connection *this = pg_get_connection_safe( self );
839
+ VALUE cSocket;
854
840
  VALUE socket_io = this->socket_io;
855
841
 
856
842
  if ( !RTEST(socket_io) ) {
@@ -859,16 +845,19 @@ pgconn_socket_io(VALUE self)
859
845
 
860
846
  #ifdef _WIN32
861
847
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
848
+ if( ruby_sd == -1 ){
849
+ rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
850
+ }
851
+ this->ruby_sd = ruby_sd;
862
852
  #else
863
853
  ruby_sd = sd;
864
854
  #endif
865
855
 
866
- socket_io = rb_funcall( rb_cIO, rb_intern("for_fd"), 1, INT2NUM(ruby_sd) );
856
+ cSocket = rb_const_get(rb_cObject, rb_intern("BasicSocket"));
857
+ socket_io = rb_funcall( cSocket, rb_intern("for_fd"), 1, INT2NUM(ruby_sd));
867
858
 
868
- /* Disable autoclose feature, when supported */
869
- if( rb_respond_to(socket_io, id_autoclose) ){
870
- rb_funcall( socket_io, id_autoclose, 1, Qfalse );
871
- }
859
+ /* Disable autoclose feature */
860
+ rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
872
861
 
873
862
  this->socket_io = socket_io;
874
863
  }
@@ -876,8 +865,6 @@ pgconn_socket_io(VALUE self)
876
865
  return socket_io;
877
866
  }
878
867
 
879
- #endif
880
-
881
868
  /*
882
869
  * call-seq:
883
870
  * conn.backend_pid() -> Integer
@@ -892,6 +879,51 @@ pgconn_backend_pid(VALUE self)
892
879
  return INT2NUM(PQbackendPID(pg_get_pgconn(self)));
893
880
  }
894
881
 
882
+ typedef struct
883
+ {
884
+ struct sockaddr_storage addr;
885
+ socklen_t salen;
886
+ } SockAddr;
887
+
888
+ /* Copy of struct pg_cancel from libpq-int.h
889
+ *
890
+ * See https://github.com/postgres/postgres/blame/master/src/interfaces/libpq/libpq-int.h#L577-L586
891
+ */
892
+ struct pg_cancel
893
+ {
894
+ SockAddr raddr; /* Remote address */
895
+ int be_pid; /* PID of backend --- needed for cancels */
896
+ int be_key; /* key of backend --- needed for cancels */
897
+ };
898
+
899
+ /*
900
+ * call-seq:
901
+ * conn.backend_key() -> Integer
902
+ *
903
+ * Returns the key of the backend server process for this connection.
904
+ * This key can be used to cancel queries on the server.
905
+ */
906
+ static VALUE
907
+ pgconn_backend_key(VALUE self)
908
+ {
909
+ int be_key;
910
+ struct pg_cancel *cancel;
911
+ PGconn *conn = pg_get_pgconn(self);
912
+
913
+ cancel = (struct pg_cancel*)PQgetCancel(conn);
914
+ if(cancel == NULL)
915
+ rb_raise(rb_ePGerror,"Invalid connection!");
916
+
917
+ if( cancel->be_pid != PQbackendPID(conn) )
918
+ rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
919
+
920
+ be_key = cancel->be_key;
921
+
922
+ PQfreeCancel(cancel);
923
+
924
+ return INT2NUM(be_key);
925
+ }
926
+
895
927
  /*
896
928
  * call-seq:
897
929
  * conn.connection_needs_password() -> Boolean
@@ -922,44 +954,35 @@ pgconn_connection_used_password(VALUE self)
922
954
  /* :TODO: get_ssl */
923
955
 
924
956
 
925
- static VALUE pgconn_exec_params( int, VALUE *, VALUE );
957
+ static VALUE pgconn_sync_exec_params( int, VALUE *, VALUE );
926
958
 
927
959
  /*
928
960
  * call-seq:
929
- * conn.exec(sql) -> PG::Result
930
- * conn.exec(sql) {|pg_result| block }
931
- *
932
- * Sends SQL query request specified by _sql_ to PostgreSQL.
933
- * Returns a PG::Result instance on success.
934
- * On failure, it raises a PG::Error.
961
+ * conn.sync_exec(sql) -> PG::Result
962
+ * conn.sync_exec(sql) {|pg_result| block }
935
963
  *
936
- * For backward compatibility, if you pass more than one parameter to this method,
937
- * it will call #exec_params for you. New code should explicitly use #exec_params if
938
- * argument placeholders are used.
964
+ * This function has the same behavior as #async_exec, but is implemented using the synchronous command processing API of libpq.
965
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
939
966
  *
940
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
941
- * and the PG::Result object will automatically be cleared when the block terminates.
942
- * In this instance, <code>conn.exec</code> returns the value of the block.
967
+ * Both #sync_exec and #async_exec release the GVL while waiting for server response, so that concurrent threads will get executed.
968
+ * However #async_exec has two advantages:
943
969
  *
944
- * #exec is implemented on the synchronous command processing API of libpq, whereas
945
- * #async_exec is implemented on the asynchronous API.
946
- * #exec is somewhat faster that #async_exec, but blocks any signals to be processed until
947
- * the query is finished. This is most notably visible by a delayed reaction to Control+C.
948
- * Both methods ensure that other threads can process while waiting for the server to
949
- * complete the request.
970
+ * 1. #async_exec can be aborted by signals (like Ctrl-C), while #exec blocks signal processing until the query is answered.
971
+ * 2. Ruby VM gets notified about IO blocked operations and can pass them through <tt>Fiber.scheduler</tt>.
972
+ * So only <tt>async_*</tt> methods are compatible to event based schedulers like the async gem.
950
973
  */
951
974
  static VALUE
952
- pgconn_exec(int argc, VALUE *argv, VALUE self)
975
+ pgconn_sync_exec(int argc, VALUE *argv, VALUE self)
953
976
  {
954
- PGconn *conn = pg_get_pgconn(self);
977
+ t_pg_connection *this = pg_get_connection_safe( self );
955
978
  PGresult *result = NULL;
956
979
  VALUE rb_pgresult;
957
980
 
958
- /* If called with no parameters, use PQexec */
959
- if ( argc == 1 ) {
981
+ /* If called with no or nil parameters, use PQexec for compatibility */
982
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
960
983
  VALUE query_str = argv[0];
961
984
 
962
- result = gvl_PQexec(conn, pg_cstr_enc(query_str, ENCODING_GET(self)));
985
+ result = gvl_PQexec(this->pgconn, pg_cstr_enc(query_str, this->enc_idx));
963
986
  rb_pgresult = pg_new_result(result, self);
964
987
  pg_result_check(rb_pgresult);
965
988
  if (rb_block_given_p()) {
@@ -967,11 +990,10 @@ pgconn_exec(int argc, VALUE *argv, VALUE self)
967
990
  }
968
991
  return rb_pgresult;
969
992
  }
993
+ pg_deprecated(0, ("forwarding exec to exec_params is deprecated"));
970
994
 
971
995
  /* Otherwise, just call #exec_params instead for backward-compatibility */
972
- else {
973
- return pgconn_exec_params( argc, argv, self );
974
- }
996
+ return pgconn_sync_exec_params( argc, argv, self );
975
997
 
976
998
  }
977
999
 
@@ -1003,7 +1025,7 @@ struct query_params_data {
1003
1025
  * Filled by alloc_query_params()
1004
1026
  */
1005
1027
 
1006
- /* Wraps the pointer of allocated memory, if function parameters dont't
1028
+ /* Wraps the pointer of allocated memory, if function parameters don't
1007
1029
  * fit in the memory_pool below.
1008
1030
  */
1009
1031
  VALUE heap_pool;
@@ -1021,7 +1043,7 @@ struct query_params_data {
1021
1043
  Oid *types;
1022
1044
 
1023
1045
  /* This array takes the string values for the timeframe of the query,
1024
- * if param value convertion is required
1046
+ * if param value conversion is required
1025
1047
  */
1026
1048
  VALUE gc_array;
1027
1049
 
@@ -1035,8 +1057,9 @@ struct query_params_data {
1035
1057
  };
1036
1058
 
1037
1059
  static void
1038
- free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1060
+ free_typecast_heap_chain(void *_chain_entry)
1039
1061
  {
1062
+ struct linked_typecast_data *chain_entry = (struct linked_typecast_data *)_chain_entry;
1040
1063
  while(chain_entry){
1041
1064
  struct linked_typecast_data *next = chain_entry->next;
1042
1065
  xfree(chain_entry);
@@ -1044,6 +1067,18 @@ free_typecast_heap_chain(struct linked_typecast_data *chain_entry)
1044
1067
  }
1045
1068
  }
1046
1069
 
1070
+ static const rb_data_type_t pg_typecast_buffer_type = {
1071
+ "PG::Connection typecast buffer chain",
1072
+ {
1073
+ (RUBY_DATA_FUNC) NULL,
1074
+ free_typecast_heap_chain,
1075
+ (size_t (*)(const void *))NULL,
1076
+ },
1077
+ 0,
1078
+ 0,
1079
+ RUBY_TYPED_FREE_IMMEDIATELY,
1080
+ };
1081
+
1047
1082
  static char *
1048
1083
  alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1049
1084
  {
@@ -1054,17 +1089,28 @@ alloc_typecast_buf( VALUE *typecast_heap_chain, int len )
1054
1089
  /* Did we already wrap a memory chain per T_DATA object? */
1055
1090
  if( NIL_P( *typecast_heap_chain ) ){
1056
1091
  /* Leave free'ing of the buffer chain to the GC, when paramsData has left the stack */
1057
- *typecast_heap_chain = Data_Wrap_Struct( rb_cObject, NULL, free_typecast_heap_chain, allocated );
1092
+ *typecast_heap_chain = TypedData_Wrap_Struct( rb_cObject, &pg_typecast_buffer_type, allocated );
1058
1093
  allocated->next = NULL;
1059
1094
  } else {
1060
1095
  /* Append to the chain */
1061
- allocated->next = DATA_PTR( *typecast_heap_chain );
1062
- DATA_PTR( *typecast_heap_chain ) = allocated;
1096
+ allocated->next = RTYPEDDATA_DATA( *typecast_heap_chain );
1097
+ RTYPEDDATA_DATA( *typecast_heap_chain ) = allocated;
1063
1098
  }
1064
1099
 
1065
1100
  return &allocated->data[0];
1066
1101
  }
1067
1102
 
1103
+ static const rb_data_type_t pg_query_heap_pool_type = {
1104
+ "PG::Connection query heap pool",
1105
+ {
1106
+ (RUBY_DATA_FUNC) NULL,
1107
+ RUBY_TYPED_DEFAULT_FREE,
1108
+ (size_t (*)(const void *))NULL,
1109
+ },
1110
+ 0,
1111
+ 0,
1112
+ RUBY_TYPED_FREE_IMMEDIATELY,
1113
+ };
1068
1114
 
1069
1115
  static int
1070
1116
  alloc_query_params(struct query_params_data *paramsData)
@@ -1079,7 +1125,7 @@ alloc_query_params(struct query_params_data *paramsData)
1079
1125
 
1080
1126
  Check_Type(paramsData->params, T_ARRAY);
1081
1127
 
1082
- p_typemap = DATA_PTR( paramsData->typemap );
1128
+ p_typemap = RTYPEDDATA_DATA( paramsData->typemap );
1083
1129
  p_typemap->funcs.fit_to_query( paramsData->typemap, paramsData->params );
1084
1130
 
1085
1131
  paramsData->heap_pool = Qnil;
@@ -1098,7 +1144,7 @@ alloc_query_params(struct query_params_data *paramsData)
1098
1144
  /* Allocate one combined memory pool for all possible function parameters */
1099
1145
  memory_pool = (char*)xmalloc( required_pool_size );
1100
1146
  /* Leave free'ing of the buffer to the GC, when paramsData has left the stack */
1101
- paramsData->heap_pool = Data_Wrap_Struct( rb_cObject, NULL, -1, memory_pool );
1147
+ paramsData->heap_pool = TypedData_Wrap_Struct( rb_cObject, &pg_query_heap_pool_type, memory_pool );
1102
1148
  required_pool_size = 0;
1103
1149
  }else{
1104
1150
  /* Use stack memory for function parameters */
@@ -1211,85 +1257,52 @@ pgconn_query_assign_typemap( VALUE self, struct query_params_data *paramsData )
1211
1257
  /* Use default typemap for queries. It's type is checked when assigned. */
1212
1258
  paramsData->typemap = pg_get_connection(self)->type_map_for_queries;
1213
1259
  }else{
1260
+ t_typemap *tm;
1261
+ UNUSED(tm);
1262
+
1214
1263
  /* Check type of method param */
1215
- if ( !rb_obj_is_kind_of(paramsData->typemap, rb_cTypeMap) ) {
1216
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
1217
- rb_obj_classname( paramsData->typemap ) );
1218
- }
1219
- Check_Type( paramsData->typemap, T_DATA );
1264
+ TypedData_Get_Struct(paramsData->typemap, t_typemap, &pg_typemap_type, tm);
1220
1265
  }
1221
1266
  }
1222
1267
 
1223
1268
  /*
1224
1269
  * call-seq:
1225
- * conn.exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1226
- * conn.exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1227
- *
1228
- * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
1229
- * for parameters.
1230
- *
1231
- * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
1270
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) -> PG::Result
1271
+ * conn.sync_exec_params(sql, params[, result_format[, type_map]] ) {|pg_result| block }
1232
1272
  *
1233
- * +params+ is an array of the bind parameters for the SQL query.
1234
- * Each element of the +params+ array may be either:
1235
- * a hash of the form:
1236
- * {:value => String (value of bind parameter)
1237
- * :type => Integer (oid of type of bind parameter)
1238
- * :format => Integer (0 for text, 1 for binary)
1239
- * }
1240
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1241
- * { :value => <string value>, :type => 0, :format => 0 }
1242
- *
1243
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1244
- * inside the SQL query. The 0th element of the +params+ array is bound
1245
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1246
- *
1247
- * If the types are not specified, they will be inferred by PostgreSQL.
1248
- * Instead of specifying type oids, it's recommended to simply add
1249
- * explicit casts in the query to ensure that the right type is used.
1250
- *
1251
- * For example: "SELECT $1::int"
1252
- *
1253
- * The optional +result_format+ should be 0 for text results, 1
1254
- * for binary.
1255
- *
1256
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1257
- * This will type cast the params form various Ruby types before transmission
1258
- * based on the encoders defined by the type map. When a type encoder is used
1259
- * the format and oid of a given bind parameter are retrieved from the encoder
1260
- * instead out of the hash form described above.
1261
- *
1262
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1263
- * and the PG::Result object will automatically be cleared when the block terminates.
1264
- * In this instance, <code>conn.exec</code> returns the value of the block.
1273
+ * This function has the same behavior as #async_exec_params, but is implemented using the synchronous command processing API of libpq.
1274
+ * See #async_exec for the differences between the two API variants.
1275
+ * It's not recommended to use explicit sync or async variants but #exec_params instead, unless you have a good reason to do so.
1265
1276
  */
1266
1277
  static VALUE
1267
- pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1278
+ pgconn_sync_exec_params( int argc, VALUE *argv, VALUE self )
1268
1279
  {
1269
- PGconn *conn = pg_get_pgconn(self);
1280
+ t_pg_connection *this = pg_get_connection_safe( self );
1270
1281
  PGresult *result = NULL;
1271
1282
  VALUE rb_pgresult;
1272
1283
  VALUE command, in_res_fmt;
1273
1284
  int nParams;
1274
1285
  int resultFormat;
1275
- struct query_params_data paramsData = { ENCODING_GET(self) };
1286
+ struct query_params_data paramsData = { this->enc_idx };
1276
1287
 
1288
+ /* For compatibility we accept 1 to 4 parameters */
1277
1289
  rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1278
1290
  paramsData.with_types = 1;
1279
1291
 
1280
1292
  /*
1281
- * Handle the edge-case where the caller is coming from #exec, but passed an explict +nil+
1282
- * for the second parameter.
1293
+ * For backward compatibility no or +nil+ for the second parameter
1294
+ * is passed to #exec
1283
1295
  */
1284
1296
  if ( NIL_P(paramsData.params) ) {
1285
- return pgconn_exec( 1, argv, self );
1297
+ pg_deprecated(1, ("forwarding exec_params to exec is deprecated"));
1298
+ return pgconn_sync_exec( 1, argv, self );
1286
1299
  }
1287
1300
  pgconn_query_assign_typemap( self, &paramsData );
1288
1301
 
1289
1302
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1290
1303
  nParams = alloc_query_params( &paramsData );
1291
1304
 
1292
- result = gvl_PQexecParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1305
+ result = gvl_PQexecParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1293
1306
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1294
1307
 
1295
1308
  free_query_params( &paramsData );
@@ -1306,28 +1319,16 @@ pgconn_exec_params( int argc, VALUE *argv, VALUE self )
1306
1319
 
1307
1320
  /*
1308
1321
  * call-seq:
1309
- * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1322
+ * conn.sync_prepare(stmt_name, sql [, param_types ] ) -> PG::Result
1310
1323
  *
1311
- * Prepares statement _sql_ with name _name_ to be executed later.
1312
- * Returns a PG::Result instance on success.
1313
- * On failure, it raises a PG::Error.
1314
- *
1315
- * +param_types+ is an optional parameter to specify the Oids of the
1316
- * types of the parameters.
1317
- *
1318
- * If the types are not specified, they will be inferred by PostgreSQL.
1319
- * Instead of specifying type oids, it's recommended to simply add
1320
- * explicit casts in the query to ensure that the right type is used.
1321
- *
1322
- * For example: "SELECT $1::int"
1323
- *
1324
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1325
- * inside the SQL query.
1324
+ * This function has the same behavior as #async_prepare, but is implemented using the synchronous command processing API of libpq.
1325
+ * See #async_exec for the differences between the two API variants.
1326
+ * It's not recommended to use explicit sync or async variants but #prepare instead, unless you have a good reason to do so.
1326
1327
  */
1327
1328
  static VALUE
1328
- pgconn_prepare(int argc, VALUE *argv, VALUE self)
1329
+ pgconn_sync_prepare(int argc, VALUE *argv, VALUE self)
1329
1330
  {
1330
- PGconn *conn = pg_get_pgconn(self);
1331
+ t_pg_connection *this = pg_get_connection_safe( self );
1331
1332
  PGresult *result = NULL;
1332
1333
  VALUE rb_pgresult;
1333
1334
  VALUE name, command, in_paramtypes;
@@ -1337,7 +1338,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1337
1338
  Oid *paramTypes = NULL;
1338
1339
  const char *name_cstr;
1339
1340
  const char *command_cstr;
1340
- int enc_idx = ENCODING_GET(self);
1341
+ int enc_idx = this->enc_idx;
1341
1342
 
1342
1343
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1343
1344
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1355,7 +1356,7 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1355
1356
  paramTypes[i] = NUM2UINT(param);
1356
1357
  }
1357
1358
  }
1358
- result = gvl_PQprepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1359
+ result = gvl_PQprepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1359
1360
 
1360
1361
  xfree(paramTypes);
1361
1362
 
@@ -1366,49 +1367,23 @@ pgconn_prepare(int argc, VALUE *argv, VALUE self)
1366
1367
 
1367
1368
  /*
1368
1369
  * call-seq:
1369
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1370
- * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1371
- *
1372
- * Execute prepared named statement specified by _statement_name_.
1373
- * Returns a PG::Result instance on success.
1374
- * On failure, it raises a PG::Error.
1375
- *
1376
- * +params+ is an array of the optional bind parameters for the
1377
- * SQL query. Each element of the +params+ array may be either:
1378
- * a hash of the form:
1379
- * {:value => String (value of bind parameter)
1380
- * :format => Integer (0 for text, 1 for binary)
1381
- * }
1382
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1383
- * { :value => <string value>, :format => 0 }
1384
- *
1385
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1386
- * inside the SQL query. The 0th element of the +params+ array is bound
1387
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1388
- *
1389
- * The optional +result_format+ should be 0 for text results, 1
1390
- * for binary.
1391
- *
1392
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1393
- * This will type cast the params form various Ruby types before transmission
1394
- * based on the encoders defined by the type map. When a type encoder is used
1395
- * the format and oid of a given bind parameter are retrieved from the encoder
1396
- * instead out of the hash form described above.
1370
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
1371
+ * conn.sync_exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
1397
1372
  *
1398
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
1399
- * and the PG::Result object will automatically be cleared when the block terminates.
1400
- * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
1373
+ * This function has the same behavior as #async_exec_prepared, but is implemented using the synchronous command processing API of libpq.
1374
+ * See #async_exec for the differences between the two API variants.
1375
+ * It's not recommended to use explicit sync or async variants but #exec_prepared instead, unless you have a good reason to do so.
1401
1376
  */
1402
1377
  static VALUE
1403
- pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1378
+ pgconn_sync_exec_prepared(int argc, VALUE *argv, VALUE self)
1404
1379
  {
1405
- PGconn *conn = pg_get_pgconn(self);
1380
+ t_pg_connection *this = pg_get_connection_safe( self );
1406
1381
  PGresult *result = NULL;
1407
1382
  VALUE rb_pgresult;
1408
1383
  VALUE name, in_res_fmt;
1409
1384
  int nParams;
1410
1385
  int resultFormat;
1411
- struct query_params_data paramsData = { ENCODING_GET(self) };
1386
+ struct query_params_data paramsData = { this->enc_idx };
1412
1387
 
1413
1388
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1414
1389
  paramsData.with_types = 0;
@@ -1421,7 +1396,7 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1421
1396
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1422
1397
  nParams = alloc_query_params( &paramsData );
1423
1398
 
1424
- result = gvl_PQexecPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1399
+ result = gvl_PQexecPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1425
1400
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1426
1401
  resultFormat);
1427
1402
 
@@ -1438,25 +1413,26 @@ pgconn_exec_prepared(int argc, VALUE *argv, VALUE self)
1438
1413
 
1439
1414
  /*
1440
1415
  * call-seq:
1441
- * conn.describe_prepared( statement_name ) -> PG::Result
1416
+ * conn.sync_describe_prepared( statement_name ) -> PG::Result
1442
1417
  *
1443
- * Retrieve information about the prepared statement
1444
- * _statement_name_.
1418
+ * This function has the same behavior as #async_describe_prepared, but is implemented using the synchronous command processing API of libpq.
1419
+ * See #async_exec for the differences between the two API variants.
1420
+ * It's not recommended to use explicit sync or async variants but #describe_prepared instead, unless you have a good reason to do so.
1445
1421
  */
1446
1422
  static VALUE
1447
- pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1423
+ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1448
1424
  {
1449
1425
  PGresult *result;
1450
1426
  VALUE rb_pgresult;
1451
- PGconn *conn = pg_get_pgconn(self);
1427
+ t_pg_connection *this = pg_get_connection_safe( self );
1452
1428
  const char *stmt;
1453
1429
  if(NIL_P(stmt_name)) {
1454
1430
  stmt = NULL;
1455
1431
  }
1456
1432
  else {
1457
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1433
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1458
1434
  }
1459
- result = gvl_PQdescribePrepared(conn, stmt);
1435
+ result = gvl_PQdescribePrepared(this->pgconn, stmt);
1460
1436
  rb_pgresult = pg_new_result(result, self);
1461
1437
  pg_result_check(rb_pgresult);
1462
1438
  return rb_pgresult;
@@ -1465,25 +1441,27 @@ pgconn_describe_prepared(VALUE self, VALUE stmt_name)
1465
1441
 
1466
1442
  /*
1467
1443
  * call-seq:
1468
- * conn.describe_portal( portal_name ) -> PG::Result
1444
+ * conn.sync_describe_portal( portal_name ) -> PG::Result
1469
1445
  *
1470
- * Retrieve information about the portal _portal_name_.
1446
+ * This function has the same behavior as #async_describe_portal, but is implemented using the synchronous command processing API of libpq.
1447
+ * See #async_exec for the differences between the two API variants.
1448
+ * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1471
1449
  */
1472
1450
  static VALUE
1473
- pgconn_describe_portal(self, stmt_name)
1451
+ pgconn_sync_describe_portal(self, stmt_name)
1474
1452
  VALUE self, stmt_name;
1475
1453
  {
1476
1454
  PGresult *result;
1477
1455
  VALUE rb_pgresult;
1478
- PGconn *conn = pg_get_pgconn(self);
1456
+ t_pg_connection *this = pg_get_connection_safe( self );
1479
1457
  const char *stmt;
1480
1458
  if(NIL_P(stmt_name)) {
1481
1459
  stmt = NULL;
1482
1460
  }
1483
1461
  else {
1484
- stmt = pg_cstr_enc(stmt_name, ENCODING_GET(self));
1462
+ stmt = pg_cstr_enc(stmt_name, this->enc_idx);
1485
1463
  }
1486
- result = gvl_PQdescribePortal(conn, stmt);
1464
+ result = gvl_PQdescribePortal(this->pgconn, stmt);
1487
1465
  rb_pgresult = pg_new_result(result, self);
1488
1466
  pg_result_check(rb_pgresult);
1489
1467
  return rb_pgresult;
@@ -1505,6 +1483,9 @@ pgconn_describe_portal(self, stmt_name)
1505
1483
  * * +PGRES_NONFATAL_ERROR+
1506
1484
  * * +PGRES_FATAL_ERROR+
1507
1485
  * * +PGRES_COPY_BOTH+
1486
+ * * +PGRES_SINGLE_TUPLE+
1487
+ * * +PGRES_PIPELINE_SYNC+
1488
+ * * +PGRES_PIPELINE_ABORTED+
1508
1489
  */
1509
1490
  static VALUE
1510
1491
  pgconn_make_empty_pgresult(VALUE self, VALUE status)
@@ -1530,13 +1511,15 @@ pgconn_make_empty_pgresult(VALUE self, VALUE status)
1530
1511
  * Consider using exec_params, which avoids the need for passing values
1531
1512
  * inside of SQL commands.
1532
1513
  *
1533
- * Encoding of escaped string will be equal to client encoding of connection.
1514
+ * Character encoding of escaped string will be equal to client encoding of connection.
1534
1515
  *
1535
1516
  * NOTE: This class version of this method can only be used safely in client
1536
1517
  * programs that use a single PostgreSQL connection at a time (in this case it can
1537
1518
  * find out what it needs to know "behind the scenes"). It might give the wrong
1538
1519
  * results if used in programs that use multiple database connections; use the
1539
1520
  * same method on the connection object in such cases.
1521
+ *
1522
+ * See also convenience functions #escape_literal and #escape_identifier which also add proper quotes around the string.
1540
1523
  */
1541
1524
  static VALUE
1542
1525
  pgconn_s_escape(VALUE self, VALUE string)
@@ -1547,8 +1530,8 @@ pgconn_s_escape(VALUE self, VALUE string)
1547
1530
  int enc_idx;
1548
1531
  int singleton = !rb_obj_is_kind_of(self, rb_cPGconn);
1549
1532
 
1550
- Check_Type(string, T_STRING);
1551
- enc_idx = ENCODING_GET( singleton ? string : self );
1533
+ StringValueCStr(string);
1534
+ enc_idx = singleton ? ENCODING_GET(string) : pg_get_connection(self)->enc_idx;
1552
1535
  if( ENCODING_GET(string) != enc_idx ){
1553
1536
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1554
1537
  }
@@ -1565,7 +1548,6 @@ pgconn_s_escape(VALUE self, VALUE string)
1565
1548
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1566
1549
  }
1567
1550
  rb_str_set_len(result, size);
1568
- OBJ_INFECT(result, string);
1569
1551
 
1570
1552
  return result;
1571
1553
  }
@@ -1611,7 +1593,6 @@ pgconn_s_escape_bytea(VALUE self, VALUE str)
1611
1593
  }
1612
1594
 
1613
1595
  ret = rb_str_new((char*)to, to_len - 1);
1614
- OBJ_INFECT(ret, str);
1615
1596
  PQfreemem(to);
1616
1597
  return ret;
1617
1598
  }
@@ -1641,50 +1622,47 @@ pgconn_s_unescape_bytea(VALUE self, VALUE str)
1641
1622
  to = PQunescapeBytea(from, &to_len);
1642
1623
 
1643
1624
  ret = rb_str_new((char*)to, to_len);
1644
- OBJ_INFECT(ret, str);
1645
1625
  PQfreemem(to);
1646
1626
  return ret;
1647
1627
  }
1648
1628
 
1649
- #ifdef HAVE_PQESCAPELITERAL
1650
1629
  /*
1651
1630
  * call-seq:
1652
1631
  * conn.escape_literal( str ) -> String
1653
1632
  *
1654
1633
  * Escape an arbitrary String +str+ as a literal.
1634
+ *
1635
+ * See also PG::TextEncoder::QuotedLiteral for a type cast integrated version of this function.
1655
1636
  */
1656
1637
  static VALUE
1657
1638
  pgconn_escape_literal(VALUE self, VALUE string)
1658
1639
  {
1659
- PGconn *conn = pg_get_pgconn(self);
1640
+ t_pg_connection *this = pg_get_connection_safe( self );
1660
1641
  char *escaped = NULL;
1661
1642
  VALUE error;
1662
1643
  VALUE result = Qnil;
1663
- int enc_idx = ENCODING_GET(self);
1644
+ int enc_idx = this->enc_idx;
1664
1645
 
1665
- Check_Type(string, T_STRING);
1646
+ StringValueCStr(string);
1666
1647
  if( ENCODING_GET(string) != enc_idx ){
1667
1648
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1668
1649
  }
1669
1650
 
1670
- escaped = PQescapeLiteral(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1651
+ escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1671
1652
  if (escaped == NULL)
1672
1653
  {
1673
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1654
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1674
1655
  rb_iv_set(error, "@connection", self);
1675
1656
  rb_exc_raise(error);
1676
1657
  return Qnil;
1677
1658
  }
1678
1659
  result = rb_str_new2(escaped);
1679
1660
  PQfreemem(escaped);
1680
- OBJ_INFECT(result, string);
1681
1661
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1682
1662
 
1683
1663
  return result;
1684
1664
  }
1685
- #endif
1686
1665
 
1687
- #ifdef HAVE_PQESCAPEIDENTIFIER
1688
1666
  /*
1689
1667
  * call-seq:
1690
1668
  * conn.escape_identifier( str ) -> String
@@ -1698,35 +1676,32 @@ pgconn_escape_literal(VALUE self, VALUE string)
1698
1676
  static VALUE
1699
1677
  pgconn_escape_identifier(VALUE self, VALUE string)
1700
1678
  {
1701
- PGconn *conn = pg_get_pgconn(self);
1679
+ t_pg_connection *this = pg_get_connection_safe( self );
1702
1680
  char *escaped = NULL;
1703
1681
  VALUE error;
1704
1682
  VALUE result = Qnil;
1705
- int enc_idx = ENCODING_GET(self);
1683
+ int enc_idx = this->enc_idx;
1706
1684
 
1707
- Check_Type(string, T_STRING);
1685
+ StringValueCStr(string);
1708
1686
  if( ENCODING_GET(string) != enc_idx ){
1709
1687
  string = rb_str_export_to_enc(string, rb_enc_from_index(enc_idx));
1710
1688
  }
1711
1689
 
1712
- escaped = PQescapeIdentifier(conn, RSTRING_PTR(string), RSTRING_LEN(string));
1690
+ escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1713
1691
  if (escaped == NULL)
1714
1692
  {
1715
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1693
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1716
1694
  rb_iv_set(error, "@connection", self);
1717
1695
  rb_exc_raise(error);
1718
1696
  return Qnil;
1719
1697
  }
1720
1698
  result = rb_str_new2(escaped);
1721
1699
  PQfreemem(escaped);
1722
- OBJ_INFECT(result, string);
1723
1700
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
1724
1701
 
1725
1702
  return result;
1726
1703
  }
1727
- #endif
1728
1704
 
1729
- #ifdef HAVE_PQSETSINGLEROWMODE
1730
1705
  /*
1731
1706
  * call-seq:
1732
1707
  * conn.set_single_row_mode -> self
@@ -1762,7 +1737,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1762
1737
  * # do something with the received row
1763
1738
  * end
1764
1739
  * end
1765
- *
1766
1740
  */
1767
1741
  static VALUE
1768
1742
  pgconn_set_single_row_mode(VALUE self)
@@ -1779,88 +1753,114 @@ pgconn_set_single_row_mode(VALUE self)
1779
1753
 
1780
1754
  return self;
1781
1755
  }
1782
- #endif
1756
+
1757
+ static VALUE pgconn_send_query_params(int argc, VALUE *argv, VALUE self);
1783
1758
 
1784
1759
  /*
1785
1760
  * call-seq:
1786
- * conn.send_query(sql [, params, result_format[, type_map ]] ) -> nil
1761
+ * conn.send_query(sql) -> nil
1787
1762
  *
1788
1763
  * Sends SQL query request specified by _sql_ to PostgreSQL for
1789
1764
  * asynchronous processing, and immediately returns.
1790
1765
  * On failure, it raises a PG::Error.
1791
1766
  *
1792
- * +params+ is an optional array of the bind parameters for the SQL query.
1793
- * Each element of the +params+ array may be either:
1794
- * a hash of the form:
1795
- * {:value => String (value of bind parameter)
1796
- * :type => Integer (oid of type of bind parameter)
1797
- * :format => Integer (0 for text, 1 for binary)
1798
- * }
1799
- * or, it may be a String. If it is a string, that is equivalent to the hash:
1800
- * { :value => <string value>, :type => 0, :format => 0 }
1801
- *
1802
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1803
- * inside the SQL query. The 0th element of the +params+ array is bound
1804
- * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1805
- *
1806
- * If the types are not specified, they will be inferred by PostgreSQL.
1807
- * Instead of specifying type oids, it's recommended to simply add
1808
- * explicit casts in the query to ensure that the right type is used.
1809
- *
1810
- * For example: "SELECT $1::int"
1811
- *
1812
- * The optional +result_format+ should be 0 for text results, 1
1813
- * for binary.
1814
- *
1815
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1816
- * This will type cast the params form various Ruby types before transmission
1817
- * based on the encoders defined by the type map. When a type encoder is used
1818
- * the format and oid of a given bind parameter are retrieved from the encoder
1819
- * instead out of the hash form described above.
1767
+ * For backward compatibility, if you pass more than one parameter to this method,
1768
+ * it will call #send_query_params for you. New code should explicitly use #send_query_params if
1769
+ * argument placeholders are used.
1820
1770
  *
1821
1771
  */
1822
1772
  static VALUE
1823
1773
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1824
1774
  {
1825
- PGconn *conn = pg_get_pgconn(self);
1826
- int result;
1827
- VALUE command, in_res_fmt;
1775
+ t_pg_connection *this = pg_get_connection_safe( self );
1828
1776
  VALUE error;
1829
- int nParams;
1830
- int resultFormat;
1831
- struct query_params_data paramsData = { ENCODING_GET(self) };
1832
1777
 
1833
- rb_scan_args(argc, argv, "13", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1834
- paramsData.with_types = 1;
1835
-
1836
- /* If called with no parameters, use PQsendQuery */
1837
- if(NIL_P(paramsData.params)) {
1838
- if(gvl_PQsendQuery(conn, pg_cstr_enc(command, paramsData.enc_idx)) == 0) {
1839
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1778
+ /* If called with no or nil parameters, use PQexec for compatibility */
1779
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1780
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1781
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1840
1782
  rb_iv_set(error, "@connection", self);
1841
1783
  rb_exc_raise(error);
1842
1784
  }
1785
+ pgconn_wait_for_flush( self );
1843
1786
  return Qnil;
1844
1787
  }
1845
1788
 
1789
+ pg_deprecated(2, ("forwarding async_exec to async_exec_params and send_query to send_query_params is deprecated"));
1790
+
1846
1791
  /* If called with parameters, and optionally result_format,
1847
1792
  * use PQsendQueryParams
1848
1793
  */
1794
+ return pgconn_send_query_params( argc, argv, self);
1795
+ }
1796
+
1797
+ /*
1798
+ * call-seq:
1799
+ * conn.send_query_params(sql, params [, result_format [, type_map ]] ) -> nil
1800
+ *
1801
+ * Sends SQL query request specified by _sql_ to PostgreSQL for
1802
+ * asynchronous processing, and immediately returns.
1803
+ * On failure, it raises a PG::Error.
1804
+ *
1805
+ * +params+ is an array of the bind parameters for the SQL query.
1806
+ * Each element of the +params+ array may be either:
1807
+ * a hash of the form:
1808
+ * {:value => String (value of bind parameter)
1809
+ * :type => Integer (oid of type of bind parameter)
1810
+ * :format => Integer (0 for text, 1 for binary)
1811
+ * }
1812
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
1813
+ * { :value => <string value>, :type => 0, :format => 0 }
1814
+ *
1815
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1816
+ * inside the SQL query. The 0th element of the +params+ array is bound
1817
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1818
+ *
1819
+ * If the types are not specified, they will be inferred by PostgreSQL.
1820
+ * Instead of specifying type oids, it's recommended to simply add
1821
+ * explicit casts in the query to ensure that the right type is used.
1822
+ *
1823
+ * For example: "SELECT $1::int"
1824
+ *
1825
+ * The optional +result_format+ should be 0 for text results, 1
1826
+ * for binary.
1827
+ *
1828
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1829
+ * This will type cast the params from various Ruby types before transmission
1830
+ * based on the encoders defined by the type map. When a type encoder is used
1831
+ * the format and oid of a given bind parameter are retrieved from the encoder
1832
+ * instead out of the hash form described above.
1833
+ *
1834
+ */
1835
+ static VALUE
1836
+ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1837
+ {
1838
+ t_pg_connection *this = pg_get_connection_safe( self );
1839
+ int result;
1840
+ VALUE command, in_res_fmt;
1841
+ VALUE error;
1842
+ int nParams;
1843
+ int resultFormat;
1844
+ struct query_params_data paramsData = { this->enc_idx };
1845
+
1846
+ rb_scan_args(argc, argv, "22", &command, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1847
+ paramsData.with_types = 1;
1849
1848
 
1850
1849
  pgconn_query_assign_typemap( self, &paramsData );
1851
1850
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1852
1851
  nParams = alloc_query_params( &paramsData );
1853
1852
 
1854
- result = gvl_PQsendQueryParams(conn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1853
+ result = gvl_PQsendQueryParams(this->pgconn, pg_cstr_enc(command, paramsData.enc_idx), nParams, paramsData.types,
1855
1854
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats, resultFormat);
1856
1855
 
1857
1856
  free_query_params( &paramsData );
1858
1857
 
1859
1858
  if(result == 0) {
1860
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1859
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1861
1860
  rb_iv_set(error, "@connection", self);
1862
1861
  rb_exc_raise(error);
1863
1862
  }
1863
+ pgconn_wait_for_flush( self );
1864
1864
  return Qnil;
1865
1865
  }
1866
1866
 
@@ -1881,13 +1881,13 @@ pgconn_send_query(int argc, VALUE *argv, VALUE self)
1881
1881
  *
1882
1882
  * For example: "SELECT $1::int"
1883
1883
  *
1884
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1884
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1885
1885
  * inside the SQL query.
1886
1886
  */
1887
1887
  static VALUE
1888
1888
  pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1889
1889
  {
1890
- PGconn *conn = pg_get_pgconn(self);
1890
+ t_pg_connection *this = pg_get_connection_safe( self );
1891
1891
  int result;
1892
1892
  VALUE name, command, in_paramtypes;
1893
1893
  VALUE param;
@@ -1897,7 +1897,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1897
1897
  Oid *paramTypes = NULL;
1898
1898
  const char *name_cstr;
1899
1899
  const char *command_cstr;
1900
- int enc_idx = ENCODING_GET(self);
1900
+ int enc_idx = this->enc_idx;
1901
1901
 
1902
1902
  rb_scan_args(argc, argv, "21", &name, &command, &in_paramtypes);
1903
1903
  name_cstr = pg_cstr_enc(name, enc_idx);
@@ -1915,15 +1915,16 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1915
1915
  paramTypes[i] = NUM2UINT(param);
1916
1916
  }
1917
1917
  }
1918
- result = gvl_PQsendPrepare(conn, name_cstr, command_cstr, nParams, paramTypes);
1918
+ result = gvl_PQsendPrepare(this->pgconn, name_cstr, command_cstr, nParams, paramTypes);
1919
1919
 
1920
1920
  xfree(paramTypes);
1921
1921
 
1922
1922
  if(result == 0) {
1923
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1923
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1924
1924
  rb_iv_set(error, "@connection", self);
1925
1925
  rb_exc_raise(error);
1926
1926
  }
1927
+ pgconn_wait_for_flush( self );
1927
1928
  return Qnil;
1928
1929
  }
1929
1930
 
@@ -1945,15 +1946,15 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1945
1946
  * or, it may be a String. If it is a string, that is equivalent to the hash:
1946
1947
  * { :value => <string value>, :format => 0 }
1947
1948
  *
1948
- * PostgreSQL bind parameters are represented as $1, $1, $2, etc.,
1949
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
1949
1950
  * inside the SQL query. The 0th element of the +params+ array is bound
1950
1951
  * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
1951
1952
  *
1952
1953
  * The optional +result_format+ should be 0 for text results, 1
1953
1954
  * for binary.
1954
1955
  *
1955
- * type_map can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1956
- * This will type cast the params form various Ruby types before transmission
1956
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
1957
+ * This will type cast the params from various Ruby types before transmission
1957
1958
  * based on the encoders defined by the type map. When a type encoder is used
1958
1959
  * the format and oid of a given bind parameter are retrieved from the encoder
1959
1960
  * instead out of the hash form described above.
@@ -1962,37 +1963,37 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1962
1963
  static VALUE
1963
1964
  pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1964
1965
  {
1965
- PGconn *conn = pg_get_pgconn(self);
1966
+ t_pg_connection *this = pg_get_connection_safe( self );
1966
1967
  int result;
1967
1968
  VALUE name, in_res_fmt;
1968
1969
  VALUE error;
1969
1970
  int nParams;
1970
1971
  int resultFormat;
1971
- struct query_params_data paramsData = { ENCODING_GET(self) };
1972
+ struct query_params_data paramsData = { this->enc_idx };
1972
1973
 
1973
1974
  rb_scan_args(argc, argv, "13", &name, &paramsData.params, &in_res_fmt, &paramsData.typemap);
1974
1975
  paramsData.with_types = 0;
1975
1976
 
1976
1977
  if(NIL_P(paramsData.params)) {
1977
1978
  paramsData.params = rb_ary_new2(0);
1978
- resultFormat = 0;
1979
1979
  }
1980
1980
  pgconn_query_assign_typemap( self, &paramsData );
1981
1981
 
1982
1982
  resultFormat = NIL_P(in_res_fmt) ? 0 : NUM2INT(in_res_fmt);
1983
1983
  nParams = alloc_query_params( &paramsData );
1984
1984
 
1985
- result = gvl_PQsendQueryPrepared(conn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1985
+ result = gvl_PQsendQueryPrepared(this->pgconn, pg_cstr_enc(name, paramsData.enc_idx), nParams,
1986
1986
  (const char * const *)paramsData.values, paramsData.lengths, paramsData.formats,
1987
1987
  resultFormat);
1988
1988
 
1989
1989
  free_query_params( &paramsData );
1990
1990
 
1991
1991
  if(result == 0) {
1992
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
1992
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1993
1993
  rb_iv_set(error, "@connection", self);
1994
1994
  rb_exc_raise(error);
1995
1995
  }
1996
+ pgconn_wait_for_flush( self );
1996
1997
  return Qnil;
1997
1998
  }
1998
1999
 
@@ -2007,13 +2008,14 @@ static VALUE
2007
2008
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2008
2009
  {
2009
2010
  VALUE error;
2010
- PGconn *conn = pg_get_pgconn(self);
2011
+ t_pg_connection *this = pg_get_connection_safe( self );
2011
2012
  /* returns 0 on failure */
2012
- if(gvl_PQsendDescribePrepared(conn, pg_cstr_enc(stmt_name, ENCODING_GET(self))) == 0) {
2013
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2013
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
2014
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2014
2015
  rb_iv_set(error, "@connection", self);
2015
2016
  rb_exc_raise(error);
2016
2017
  }
2018
+ pgconn_wait_for_flush( self );
2017
2019
  return Qnil;
2018
2020
  }
2019
2021
 
@@ -2029,35 +2031,20 @@ static VALUE
2029
2031
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2030
2032
  {
2031
2033
  VALUE error;
2032
- PGconn *conn = pg_get_pgconn(self);
2034
+ t_pg_connection *this = pg_get_connection_safe( self );
2033
2035
  /* returns 0 on failure */
2034
- if(gvl_PQsendDescribePortal(conn, pg_cstr_enc(portal, ENCODING_GET(self))) == 0) {
2035
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(conn));
2036
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2037
+ error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2036
2038
  rb_iv_set(error, "@connection", self);
2037
2039
  rb_exc_raise(error);
2038
2040
  }
2041
+ pgconn_wait_for_flush( self );
2039
2042
  return Qnil;
2040
2043
  }
2041
2044
 
2042
2045
 
2043
- /*
2044
- * call-seq:
2045
- * conn.get_result() -> PG::Result
2046
- * conn.get_result() {|pg_result| block }
2047
- *
2048
- * Blocks waiting for the next result from a call to
2049
- * #send_query (or another asynchronous command), and returns
2050
- * it. Returns +nil+ if no more results are available.
2051
- *
2052
- * Note: call this function repeatedly until it returns +nil+, or else
2053
- * you will not be able to issue further commands.
2054
- *
2055
- * If the optional code block is given, it will be passed <i>result</i> as an argument,
2056
- * and the PG::Result object will automatically be cleared when the block terminates.
2057
- * In this instance, <code>conn.exec</code> returns the value of the block.
2058
- */
2059
2046
  static VALUE
2060
- pgconn_get_result(VALUE self)
2047
+ pgconn_sync_get_result(VALUE self)
2061
2048
  {
2062
2049
  PGconn *conn = pg_get_pgconn(self);
2063
2050
  PGresult *result;
@@ -2090,6 +2077,7 @@ pgconn_consume_input(self)
2090
2077
  PGconn *conn = pg_get_pgconn(self);
2091
2078
  /* returns 0 on error */
2092
2079
  if(PQconsumeInput(conn) == 0) {
2080
+ pgconn_close_socket_io(self);
2093
2081
  error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2094
2082
  rb_iv_set(error, "@connection", self);
2095
2083
  rb_exc_raise(error);
@@ -2102,7 +2090,7 @@ pgconn_consume_input(self)
2102
2090
  * conn.is_busy() -> Boolean
2103
2091
  *
2104
2092
  * Returns +true+ if a command is busy, that is, if
2105
- * PQgetResult would block. Otherwise returns +false+.
2093
+ * #get_result would block. Otherwise returns +false+.
2106
2094
  */
2107
2095
  static VALUE
2108
2096
  pgconn_is_busy(self)
@@ -2111,24 +2099,8 @@ pgconn_is_busy(self)
2111
2099
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2112
2100
  }
2113
2101
 
2114
- /*
2115
- * call-seq:
2116
- * conn.setnonblocking(Boolean) -> nil
2117
- *
2118
- * Sets the nonblocking status of the connection.
2119
- * In the blocking state, calls to #send_query
2120
- * will block until the message is sent to the server,
2121
- * but will not wait for the query results.
2122
- * In the nonblocking state, calls to #send_query
2123
- * will return an error if the socket is not ready for
2124
- * writing.
2125
- * Note: This function does not affect #exec, because
2126
- * that function doesn't return until the server has
2127
- * processed the query and returned the results.
2128
- * Returns +nil+.
2129
- */
2130
2102
  static VALUE
2131
- pgconn_setnonblocking(self, state)
2103
+ pgconn_sync_setnonblocking(self, state)
2132
2104
  VALUE self, state;
2133
2105
  {
2134
2106
  int arg;
@@ -2150,33 +2122,15 @@ pgconn_setnonblocking(self, state)
2150
2122
  }
2151
2123
 
2152
2124
 
2153
- /*
2154
- * call-seq:
2155
- * conn.isnonblocking() -> Boolean
2156
- *
2157
- * Returns +true+ if a command is busy, that is, if
2158
- * PQgetResult would block. Otherwise returns +false+.
2159
- */
2160
2125
  static VALUE
2161
- pgconn_isnonblocking(self)
2126
+ pgconn_sync_isnonblocking(self)
2162
2127
  VALUE self;
2163
2128
  {
2164
2129
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2165
2130
  }
2166
2131
 
2167
- /*
2168
- * call-seq:
2169
- * conn.flush() -> Boolean
2170
- *
2171
- * Attempts to flush any queued output data to the server.
2172
- * Returns +true+ if data is successfully flushed, +false+
2173
- * if not (can only return +false+ if connection is
2174
- * nonblocking.
2175
- * Raises PG::Error if some other failure occurred.
2176
- */
2177
2132
  static VALUE
2178
- pgconn_flush(self)
2179
- VALUE self;
2133
+ pgconn_sync_flush(VALUE self)
2180
2134
  {
2181
2135
  PGconn *conn = pg_get_pgconn(self);
2182
2136
  int ret;
@@ -2190,20 +2144,9 @@ pgconn_flush(self)
2190
2144
  return (ret) ? Qfalse : Qtrue;
2191
2145
  }
2192
2146
 
2193
- /*
2194
- * call-seq:
2195
- * conn.cancel() -> String
2196
- *
2197
- * Requests cancellation of the command currently being
2198
- * processed. (Only implemented in PostgreSQL >= 8.0)
2199
- *
2200
- * Returns +nil+ on success, or a string containing the
2201
- * error message if a failure occurs.
2202
- */
2203
2147
  static VALUE
2204
- pgconn_cancel(VALUE self)
2148
+ pgconn_sync_cancel(VALUE self)
2205
2149
  {
2206
- #ifdef HAVE_PQGETCANCEL
2207
2150
  char errbuf[256];
2208
2151
  PGcancel *cancel;
2209
2152
  VALUE retval;
@@ -2213,7 +2156,7 @@ pgconn_cancel(VALUE self)
2213
2156
  if(cancel == NULL)
2214
2157
  rb_raise(rb_ePGerror,"Invalid connection!");
2215
2158
 
2216
- ret = gvl_PQcancel(cancel, errbuf, 256);
2159
+ ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2217
2160
  if(ret == 1)
2218
2161
  retval = Qnil;
2219
2162
  else
@@ -2221,9 +2164,6 @@ pgconn_cancel(VALUE self)
2221
2164
 
2222
2165
  PQfreeCancel(cancel);
2223
2166
  return retval;
2224
- #else
2225
- rb_notimplement();
2226
- #endif
2227
2167
  }
2228
2168
 
2229
2169
 
@@ -2237,7 +2177,7 @@ pgconn_cancel(VALUE self)
2237
2177
  static VALUE
2238
2178
  pgconn_notifies(VALUE self)
2239
2179
  {
2240
- PGconn* conn = pg_get_pgconn(self);
2180
+ t_pg_connection *this = pg_get_connection_safe( self );
2241
2181
  PGnotify *notification;
2242
2182
  VALUE hash;
2243
2183
  VALUE sym_relname, sym_be_pid, sym_extra;
@@ -2247,17 +2187,17 @@ pgconn_notifies(VALUE self)
2247
2187
  sym_be_pid = ID2SYM(rb_intern("be_pid"));
2248
2188
  sym_extra = ID2SYM(rb_intern("extra"));
2249
2189
 
2250
- notification = gvl_PQnotifies(conn);
2190
+ notification = gvl_PQnotifies(this->pgconn);
2251
2191
  if (notification == NULL) {
2252
2192
  return Qnil;
2253
2193
  }
2254
2194
 
2255
2195
  hash = rb_hash_new();
2256
- relname = rb_tainted_str_new2(notification->relname);
2196
+ relname = rb_str_new2(notification->relname);
2257
2197
  be_pid = INT2NUM(notification->be_pid);
2258
- extra = rb_tainted_str_new2(notification->extra);
2259
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2260
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2198
+ extra = rb_str_new2(notification->extra);
2199
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2200
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2261
2201
 
2262
2202
  rb_hash_aset(hash, sym_relname, relname);
2263
2203
  rb_hash_aset(hash, sym_be_pid, be_pid);
@@ -2267,96 +2207,63 @@ pgconn_notifies(VALUE self)
2267
2207
  return hash;
2268
2208
  }
2269
2209
 
2270
- /* Win32 + Ruby 1.8 */
2271
- #if !defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2210
+ #if defined(_WIN32)
2272
2211
 
2273
- /*
2274
- * Duplicate the sockets from libpq and create temporary CRT FDs
2212
+ /* We use a specialized implementation of rb_io_wait() on Windows.
2213
+ * This is because rb_io_wait() and rb_wait_for_single_fd() are very slow on Windows.
2275
2214
  */
2276
- void create_crt_fd(fd_set *os_set, fd_set *crt_set)
2277
- {
2278
- int i;
2279
- crt_set->fd_count = os_set->fd_count;
2280
- for (i = 0; i < os_set->fd_count; i++) {
2281
- WSAPROTOCOL_INFO wsa_pi;
2282
- /* dupicate the SOCKET */
2283
- int r = WSADuplicateSocket(os_set->fd_array[i], GetCurrentProcessId(), &wsa_pi);
2284
- SOCKET s = WSASocket(wsa_pi.iAddressFamily, wsa_pi.iSocketType, wsa_pi.iProtocol, &wsa_pi, 0, 0);
2285
- /* create the CRT fd so ruby can get back to the SOCKET */
2286
- int fd = _open_osfhandle(s, O_RDWR|O_BINARY);
2287
- os_set->fd_array[i] = s;
2288
- crt_set->fd_array[i] = fd;
2289
- }
2290
- }
2291
2215
 
2292
- /*
2293
- * Clean up the CRT FDs from create_crt_fd()
2294
- */
2295
- void cleanup_crt_fd(fd_set *os_set, fd_set *crt_set)
2296
- {
2297
- int i;
2298
- for (i = 0; i < os_set->fd_count; i++) {
2299
- /* cleanup the CRT fd */
2300
- _close(crt_set->fd_array[i]);
2301
- /* cleanup the duplicated SOCKET */
2302
- closesocket(os_set->fd_array[i]);
2303
- }
2304
- }
2216
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2217
+ #include <ruby/fiber/scheduler.h>
2305
2218
  #endif
2306
2219
 
2307
- /* Win32 + Ruby 1.9+ */
2308
- #if defined( HAVE_RUBY_VM_H ) && defined( _WIN32 )
2309
- /*
2310
- * On Windows, use platform-specific strategies to wait for the socket
2311
- * instead of rb_thread_select().
2312
- */
2220
+ typedef enum {
2221
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2222
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2223
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2224
+ } pg_rb_io_event_t;
2313
2225
 
2314
2226
  int rb_w32_wait_events( HANDLE *events, int num, DWORD timeout );
2315
2227
 
2316
- /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
2317
- * and does not wait (nor sleep) any time even if timeout is given.
2318
- * Instead use the Winsock events and rb_w32_wait_events(). */
2228
+ static VALUE
2229
+ pg_rb_thread_io_wait(VALUE io, VALUE events, VALUE timeout) {
2230
+ rb_io_t *fptr;
2231
+ struct timeval ptimeout;
2319
2232
 
2320
- static void *
2321
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *) )
2322
- {
2323
- int sd = PQsocket( conn );
2324
- void *retval;
2325
2233
  struct timeval aborttime={0,0}, currtime, waittime;
2326
2234
  DWORD timeout_milisec = INFINITE;
2327
- DWORD wait_ret;
2328
- WSAEVENT hEvent;
2329
-
2330
- if ( sd < 0 )
2331
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2235
+ HANDLE hEvent = WSACreateEvent();
2332
2236
 
2333
- hEvent = WSACreateEvent();
2237
+ long rb_events = NUM2UINT(events);
2238
+ long w32_events = 0;
2239
+ DWORD wait_ret;
2334
2240
 
2335
- /* Check for connection errors (PQisBusy is true on connection errors) */
2336
- if( PQconsumeInput(conn) == 0 ) {
2337
- WSACloseEvent( hEvent );
2338
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2339
- }
2241
+ GetOpenFile((io), fptr);
2242
+ if( !NIL_P(timeout) ){
2243
+ ptimeout.tv_sec = (time_t)(NUM2DBL(timeout));
2244
+ ptimeout.tv_usec = (time_t)((NUM2DBL(timeout) - (double)ptimeout.tv_sec) * 1e6);
2340
2245
 
2341
- if ( ptimeout ) {
2342
2246
  gettimeofday(&currtime, NULL);
2343
- timeradd(&currtime, ptimeout, &aborttime);
2247
+ timeradd(&currtime, &ptimeout, &aborttime);
2344
2248
  }
2345
2249
 
2346
- while ( !(retval=is_readable(conn)) ) {
2347
- if ( WSAEventSelect(sd, hEvent, FD_READ|FD_CLOSE) == SOCKET_ERROR ) {
2250
+ if(rb_events & PG_RUBY_IO_READABLE) w32_events |= FD_READ | FD_ACCEPT | FD_CLOSE;
2251
+ if(rb_events & PG_RUBY_IO_WRITABLE) w32_events |= FD_WRITE | FD_CONNECT;
2252
+ if(rb_events & PG_RUBY_IO_PRIORITY) w32_events |= FD_OOB;
2253
+
2254
+ for(;;) {
2255
+ if ( WSAEventSelect(_get_osfhandle(fptr->fd), hEvent, w32_events) == SOCKET_ERROR ) {
2348
2256
  WSACloseEvent( hEvent );
2349
2257
  rb_raise( rb_eConnectionBad, "WSAEventSelect socket error: %d", WSAGetLastError() );
2350
2258
  }
2351
2259
 
2352
- if ( ptimeout ) {
2260
+ if ( !NIL_P(timeout) ) {
2353
2261
  gettimeofday(&currtime, NULL);
2354
2262
  timersub(&aborttime, &currtime, &waittime);
2355
2263
  timeout_milisec = (DWORD)( waittime.tv_sec * 1e3 + waittime.tv_usec / 1e3 );
2356
2264
  }
2357
2265
 
2358
- /* Is the given timeout valid? */
2359
- if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2266
+ if( NIL_P(timeout) || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2360
2267
  /* Wait for the socket to become readable before checking again */
2361
2268
  wait_ret = rb_w32_wait_events( &hEvent, 1, timeout_milisec );
2362
2269
  } else {
@@ -2365,9 +2272,11 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2365
2272
 
2366
2273
  if ( wait_ret == WAIT_TIMEOUT ) {
2367
2274
  WSACloseEvent( hEvent );
2368
- return NULL;
2275
+ return UINT2NUM(0);
2369
2276
  } else if ( wait_ret == WAIT_OBJECT_0 ) {
2277
+ WSACloseEvent( hEvent );
2370
2278
  /* The event we were waiting for. */
2279
+ return UINT2NUM(rb_events);
2371
2280
  } else if ( wait_ret == WAIT_OBJECT_0 + 1) {
2372
2281
  /* This indicates interruption from timer thread, GC, exception
2373
2282
  * from other threads etc... */
@@ -2379,42 +2288,75 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2379
2288
  WSACloseEvent( hEvent );
2380
2289
  rb_raise( rb_eConnectionBad, "Wait on socket abandoned (WaitForMultipleObjects)" );
2381
2290
  }
2382
-
2383
- /* Check for connection errors (PQisBusy is true on connection errors) */
2384
- if ( PQconsumeInput(conn) == 0 ) {
2385
- WSACloseEvent( hEvent );
2386
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2387
- }
2388
2291
  }
2292
+ }
2389
2293
 
2390
- WSACloseEvent( hEvent );
2391
- return retval;
2294
+ static VALUE
2295
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2296
+ #if defined(HAVE_RUBY_FIBER_SCHEDULER_H)
2297
+ /* We don't support Fiber.scheduler on Windows ruby-3.0 because there is no fast way to check whether a scheduler is active.
2298
+ * Fortunatelly ruby-3.1 offers a C-API for it.
2299
+ */
2300
+ VALUE scheduler = rb_fiber_scheduler_current();
2301
+
2302
+ if (!NIL_P(scheduler)) {
2303
+ return rb_io_wait(io, events, timeout);
2304
+ }
2305
+ #endif
2306
+ return pg_rb_thread_io_wait(io, events, timeout);
2392
2307
  }
2393
2308
 
2309
+ #elif defined(HAVE_RB_IO_WAIT)
2310
+
2311
+ /* Use our own function and constants names, to avoid conflicts with truffleruby-head on its road to ruby-3.0 compatibility. */
2312
+ #define pg_rb_io_wait rb_io_wait
2313
+ #define PG_RUBY_IO_READABLE RUBY_IO_READABLE
2314
+ #define PG_RUBY_IO_WRITABLE RUBY_IO_WRITABLE
2315
+ #define PG_RUBY_IO_PRIORITY RUBY_IO_PRIORITY
2316
+
2394
2317
  #else
2318
+ /* For compat with ruby < 3.0 */
2319
+
2320
+ typedef enum {
2321
+ PG_RUBY_IO_READABLE = RB_WAITFD_IN,
2322
+ PG_RUBY_IO_WRITABLE = RB_WAITFD_OUT,
2323
+ PG_RUBY_IO_PRIORITY = RB_WAITFD_PRI,
2324
+ } pg_rb_io_event_t;
2325
+
2326
+ static VALUE
2327
+ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2328
+ rb_io_t *fptr;
2329
+ struct timeval waittime;
2330
+ int res;
2331
+
2332
+ GetOpenFile((io), fptr);
2333
+ if( !NIL_P(timeout) ){
2334
+ waittime.tv_sec = (time_t)(NUM2DBL(timeout));
2335
+ waittime.tv_usec = (time_t)((NUM2DBL(timeout) - (double)waittime.tv_sec) * 1e6);
2336
+ }
2337
+ res = rb_wait_for_single_fd(fptr->fd, NUM2UINT(events), NIL_P(timeout) ? NULL : &waittime);
2395
2338
 
2396
- /* non Win32 or Win32+Ruby-1.8 */
2339
+ return UINT2NUM(res);
2340
+ }
2341
+ #endif
2397
2342
 
2398
2343
  static void *
2399
- wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2344
+ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2400
2345
  {
2401
- int sd = PQsocket( conn );
2402
- int ret;
2346
+ VALUE socket_io;
2347
+ VALUE ret;
2403
2348
  void *retval;
2404
- rb_fdset_t sd_rset;
2405
2349
  struct timeval aborttime={0,0}, currtime, waittime;
2406
- #ifdef _WIN32
2407
- rb_fdset_t crt_sd_rset;
2408
- #endif
2350
+ VALUE wait_timeout = Qnil;
2351
+ PGconn *conn = pg_get_pgconn(self);
2409
2352
 
2410
- if ( sd < 0 )
2411
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
2353
+ socket_io = pgconn_socket_io(self);
2412
2354
 
2413
2355
  /* Check for connection errors (PQisBusy is true on connection errors) */
2414
- if ( PQconsumeInput(conn) == 0 )
2356
+ if ( PQconsumeInput(conn) == 0 ) {
2357
+ pgconn_close_socket_io(self);
2415
2358
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2416
-
2417
- rb_fd_init( &sd_rset );
2359
+ }
2418
2360
 
2419
2361
  if ( ptimeout ) {
2420
2362
  gettimeofday(&currtime, NULL);
@@ -2422,59 +2364,74 @@ wait_socket_readable( PGconn *conn, struct timeval *ptimeout, void *(*is_readabl
2422
2364
  }
2423
2365
 
2424
2366
  while ( !(retval=is_readable(conn)) ) {
2425
- rb_fd_zero( &sd_rset );
2426
- rb_fd_set( sd, &sd_rset );
2427
-
2428
- #ifdef _WIN32
2429
- /* Ruby's FD_SET is modified on win32 to convert a file descriptor
2430
- * to osfhandle, but we already get a osfhandle from PQsocket().
2431
- * Therefore it's overwritten here. */
2432
- sd_rset.fd_array[0] = sd;
2433
- create_crt_fd(&sd_rset, &crt_sd_rset);
2434
- #endif
2435
-
2436
2367
  if ( ptimeout ) {
2437
2368
  gettimeofday(&currtime, NULL);
2438
2369
  timersub(&aborttime, &currtime, &waittime);
2370
+ wait_timeout = DBL2NUM((double)(waittime.tv_sec) + (double)(waittime.tv_usec) / 1000000.0);
2439
2371
  }
2440
2372
 
2441
2373
  /* Is the given timeout valid? */
2442
2374
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2443
2375
  /* Wait for the socket to become readable before checking again */
2444
- ret = rb_thread_fd_select( sd+1, &sd_rset, NULL, NULL, ptimeout ? &waittime : NULL );
2376
+ ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2445
2377
  } else {
2446
- ret = 0;
2447
- }
2448
-
2449
-
2450
- #ifdef _WIN32
2451
- cleanup_crt_fd(&sd_rset, &crt_sd_rset);
2452
- #endif
2453
-
2454
- if ( ret < 0 ){
2455
- rb_fd_term( &sd_rset );
2456
- rb_sys_fail( "rb_thread_select()" );
2378
+ ret = Qfalse;
2457
2379
  }
2458
2380
 
2459
2381
  /* Return false if the select() timed out */
2460
- if ( ret == 0 ){
2461
- rb_fd_term( &sd_rset );
2382
+ if ( ret == Qfalse ){
2462
2383
  return NULL;
2463
2384
  }
2464
2385
 
2465
2386
  /* Check for connection errors (PQisBusy is true on connection errors) */
2466
2387
  if ( PQconsumeInput(conn) == 0 ){
2467
- rb_fd_term( &sd_rset );
2388
+ pgconn_close_socket_io(self);
2468
2389
  rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2469
2390
  }
2470
2391
  }
2471
2392
 
2472
- rb_fd_term( &sd_rset );
2473
2393
  return retval;
2474
2394
  }
2475
2395
 
2396
+ /*
2397
+ * call-seq:
2398
+ * conn.flush() -> Boolean
2399
+ *
2400
+ * Attempts to flush any queued output data to the server.
2401
+ * Returns +true+ if data is successfully flushed, +false+
2402
+ * if not (can only return +false+ if connection is
2403
+ * nonblocking.
2404
+ * Raises PG::Error if some other failure occurred.
2405
+ */
2406
+ static VALUE
2407
+ pgconn_async_flush(VALUE self)
2408
+ {
2409
+ while( pgconn_sync_flush(self) == Qfalse ){
2410
+ /* wait for the socket to become read- or write-ready */
2411
+ int events;
2412
+ VALUE socket_io = pgconn_socket_io(self);
2413
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2414
+
2415
+ if (events & PG_RUBY_IO_READABLE)
2416
+ pgconn_consume_input(self);
2417
+ }
2418
+ return Qtrue;
2419
+ }
2420
+
2421
+ static VALUE
2422
+ pgconn_wait_for_flush( VALUE self ){
2423
+ if( !pg_get_connection_safe(self)->flush_data )
2424
+ return Qnil;
2425
+
2426
+ return pgconn_async_flush(self);
2427
+ }
2476
2428
 
2477
- #endif
2429
+ static VALUE
2430
+ pgconn_flush_data_set( VALUE self, VALUE enabled ){
2431
+ t_pg_connection *conn = pg_get_connection(self);
2432
+ conn->flush_data = RTEST(enabled);
2433
+ return enabled;
2434
+ }
2478
2435
 
2479
2436
  static void *
2480
2437
  notify_readable(PGconn *conn)
@@ -2484,27 +2441,20 @@ notify_readable(PGconn *conn)
2484
2441
 
2485
2442
  /*
2486
2443
  * call-seq:
2487
- * conn.wait_for_notify( [ timeout ] ) -> String
2488
- * conn.wait_for_notify( [ timeout ] ) { |event, pid| block }
2489
- * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } # PostgreSQL 9.0
2444
+ * conn.wait_for_notify( [ timeout ] ) { |event, pid, payload| block } -> String
2490
2445
  *
2491
2446
  * Blocks while waiting for notification(s), or until the optional
2492
2447
  * _timeout_ is reached, whichever comes first. _timeout_ is
2493
2448
  * measured in seconds and can be fractional.
2494
2449
  *
2495
- * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY
2496
- * event otherwise. If used in block form, passes the name of the
2497
- * NOTIFY +event+ and the generating +pid+ into the block.
2498
- *
2499
- * Under PostgreSQL 9.0 and later, if the notification is sent with
2500
- * the optional +payload+ string, it will be given to the block as the
2501
- * third argument.
2502
- *
2450
+ * Returns +nil+ if _timeout_ is reached, the name of the NOTIFY event otherwise.
2451
+ * If used in block form, passes the name of the NOTIFY +event+, the generating
2452
+ * +pid+ and the optional +payload+ string into the block.
2503
2453
  */
2504
2454
  static VALUE
2505
2455
  pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2506
2456
  {
2507
- PGconn *conn = pg_get_pgconn( self );
2457
+ t_pg_connection *this = pg_get_connection_safe( self );
2508
2458
  PGnotify *pnotification;
2509
2459
  struct timeval timeout;
2510
2460
  struct timeval *ptimeout = NULL;
@@ -2520,20 +2470,18 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2520
2470
  ptimeout = &timeout;
2521
2471
  }
2522
2472
 
2523
- pnotification = (PGnotify*) wait_socket_readable( conn, ptimeout, notify_readable);
2473
+ pnotification = (PGnotify*) wait_socket_readable( self, ptimeout, notify_readable);
2524
2474
 
2525
2475
  /* Return nil if the select timed out */
2526
2476
  if ( !pnotification ) return Qnil;
2527
2477
 
2528
- relname = rb_tainted_str_new2( pnotification->relname );
2529
- PG_ENCODING_SET_NOCHECK( relname, ENCODING_GET(self) );
2478
+ relname = rb_str_new2( pnotification->relname );
2479
+ PG_ENCODING_SET_NOCHECK( relname, this->enc_idx );
2530
2480
  be_pid = INT2NUM( pnotification->be_pid );
2531
- #ifdef HAVE_ST_NOTIFY_EXTRA
2532
2481
  if ( *pnotification->extra ) {
2533
- extra = rb_tainted_str_new2( pnotification->extra );
2534
- PG_ENCODING_SET_NOCHECK( extra, ENCODING_GET(self) );
2482
+ extra = rb_str_new2( pnotification->extra );
2483
+ PG_ENCODING_SET_NOCHECK( extra, this->enc_idx );
2535
2484
  }
2536
- #endif
2537
2485
  PQfreemem( pnotification );
2538
2486
 
2539
2487
  if ( rb_block_given_p() )
@@ -2543,27 +2491,8 @@ pgconn_wait_for_notify(int argc, VALUE *argv, VALUE self)
2543
2491
  }
2544
2492
 
2545
2493
 
2546
- /*
2547
- * call-seq:
2548
- * conn.put_copy_data( buffer [, encoder] ) -> Boolean
2549
- *
2550
- * Transmits _buffer_ as copy data to the server.
2551
- * Returns true if the data was sent, false if it was
2552
- * not sent (false is only possible if the connection
2553
- * is in nonblocking mode, and this command would block).
2554
- *
2555
- * encoder can be a PG::Coder derivation (typically PG::TextEncoder::CopyRow).
2556
- * This encodes the received data fields from an Array of Strings. Optionally
2557
- * the encoder can type cast the fields form various Ruby types in one step,
2558
- * if PG::TextEncoder::CopyRow#type_map is set accordingly.
2559
- *
2560
- * Raises an exception if an error occurs.
2561
- *
2562
- * See also #copy_data.
2563
- *
2564
- */
2565
2494
  static VALUE
2566
- pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2495
+ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2567
2496
  {
2568
2497
  int ret;
2569
2498
  int len;
@@ -2580,18 +2509,16 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2580
2509
  if( NIL_P(this->encoder_for_put_copy_data) ){
2581
2510
  buffer = value;
2582
2511
  } else {
2583
- p_coder = DATA_PTR( this->encoder_for_put_copy_data );
2512
+ p_coder = RTYPEDDATA_DATA( this->encoder_for_put_copy_data );
2584
2513
  }
2585
- } else if( rb_obj_is_kind_of(encoder, rb_cPG_Coder) ) {
2586
- Data_Get_Struct( encoder, t_pg_coder, p_coder );
2587
2514
  } else {
2588
- rb_raise( rb_eTypeError, "wrong encoder type %s (expected some kind of PG::Coder)",
2589
- rb_obj_classname( encoder ) );
2515
+ /* Check argument type and use argument encoder */
2516
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, p_coder);
2590
2517
  }
2591
2518
 
2592
2519
  if( p_coder ){
2593
2520
  t_pg_coder_enc_func enc_func;
2594
- int enc_idx = ENCODING_GET(self);
2521
+ int enc_idx = this->enc_idx;
2595
2522
 
2596
2523
  enc_func = pg_coder_enc_func( p_coder );
2597
2524
  len = enc_func( p_coder, value, NULL, &intermediate, enc_idx);
@@ -2620,61 +2547,31 @@ pgconn_put_copy_data(int argc, VALUE *argv, VALUE self)
2620
2547
  return (ret) ? Qtrue : Qfalse;
2621
2548
  }
2622
2549
 
2623
- /*
2624
- * call-seq:
2625
- * conn.put_copy_end( [ error_message ] ) -> Boolean
2626
- *
2627
- * Sends end-of-data indication to the server.
2628
- *
2629
- * _error_message_ is an optional parameter, and if set,
2630
- * forces the COPY command to fail with the string
2631
- * _error_message_.
2632
- *
2633
- * Returns true if the end-of-data was sent, false if it was
2634
- * not sent (false is only possible if the connection
2635
- * is in nonblocking mode, and this command would block).
2636
- */
2637
2550
  static VALUE
2638
- pgconn_put_copy_end(int argc, VALUE *argv, VALUE self)
2551
+ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2639
2552
  {
2640
2553
  VALUE str;
2641
2554
  VALUE error;
2642
2555
  int ret;
2643
2556
  const char *error_message = NULL;
2644
- PGconn *conn = pg_get_pgconn(self);
2557
+ t_pg_connection *this = pg_get_connection_safe( self );
2645
2558
 
2646
2559
  if (rb_scan_args(argc, argv, "01", &str) == 0)
2647
2560
  error_message = NULL;
2648
2561
  else
2649
- error_message = pg_cstr_enc(str, ENCODING_GET(self));
2562
+ error_message = pg_cstr_enc(str, this->enc_idx);
2650
2563
 
2651
- ret = gvl_PQputCopyEnd(conn, error_message);
2564
+ ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2652
2565
  if(ret == -1) {
2653
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2566
+ error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2654
2567
  rb_iv_set(error, "@connection", self);
2655
2568
  rb_exc_raise(error);
2656
2569
  }
2657
2570
  return (ret) ? Qtrue : Qfalse;
2658
2571
  }
2659
2572
 
2660
- /*
2661
- * call-seq:
2662
- * conn.get_copy_data( [ async = false [, decoder = nil ]] ) -> String
2663
- *
2664
- * Return a string containing one row of data, +nil+
2665
- * if the copy is done, or +false+ if the call would
2666
- * block (only possible if _async_ is true).
2667
- *
2668
- * decoder can be a PG::Coder derivation (typically PG::TextDecoder::CopyRow).
2669
- * This decodes the received data fields as Array of Strings. Optionally
2670
- * the decoder can type cast the fields to various Ruby types in one step,
2671
- * if PG::TextDecoder::CopyRow#type_map is set accordingly.
2672
- *
2673
- * See also #copy_data.
2674
- *
2675
- */
2676
2573
  static VALUE
2677
- pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2574
+ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2678
2575
  {
2679
2576
  VALUE async_in;
2680
2577
  VALUE error;
@@ -2689,13 +2586,11 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2689
2586
 
2690
2587
  if( NIL_P(decoder) ){
2691
2588
  if( !NIL_P(this->decoder_for_get_copy_data) ){
2692
- p_coder = DATA_PTR( this->decoder_for_get_copy_data );
2589
+ p_coder = RTYPEDDATA_DATA( this->decoder_for_get_copy_data );
2693
2590
  }
2694
- } else if( rb_obj_is_kind_of(decoder, rb_cPG_Coder) ) {
2695
- Data_Get_Struct( decoder, t_pg_coder, p_coder );
2696
2591
  } else {
2697
- rb_raise( rb_eTypeError, "wrong decoder type %s (expected some kind of PG::Coder)",
2698
- rb_obj_classname( decoder ) );
2592
+ /* Check argument type and use argument decoder */
2593
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, p_coder);
2699
2594
  }
2700
2595
 
2701
2596
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
@@ -2713,9 +2608,9 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2713
2608
 
2714
2609
  if( p_coder ){
2715
2610
  t_pg_coder_dec_func dec_func = pg_coder_dec_func( p_coder, p_coder->format );
2716
- result = dec_func( p_coder, buffer, ret, 0, 0, ENCODING_GET(self) );
2611
+ result = dec_func( p_coder, buffer, ret, 0, 0, this->enc_idx );
2717
2612
  } else {
2718
- result = rb_tainted_str_new(buffer, ret);
2613
+ result = rb_str_new(buffer, ret);
2719
2614
  }
2720
2615
 
2721
2616
  PQfreemem(buffer);
@@ -2728,9 +2623,16 @@ pgconn_get_copy_data(int argc, VALUE *argv, VALUE self )
2728
2623
  *
2729
2624
  * Sets connection's verbosity to _verbosity_ and returns
2730
2625
  * the previous setting. Available settings are:
2626
+ *
2731
2627
  * * PQERRORS_TERSE
2732
2628
  * * PQERRORS_DEFAULT
2733
2629
  * * PQERRORS_VERBOSE
2630
+ * * PQERRORS_SQLSTATE
2631
+ *
2632
+ * Changing the verbosity does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2633
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different verbosity.)
2634
+ *
2635
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORVERBOSITY].
2734
2636
  */
2735
2637
  static VALUE
2736
2638
  pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
@@ -2740,6 +2642,37 @@ pgconn_set_error_verbosity(VALUE self, VALUE in_verbosity)
2740
2642
  return INT2FIX(PQsetErrorVerbosity(conn, verbosity));
2741
2643
  }
2742
2644
 
2645
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
2646
+ /*
2647
+ * call-seq:
2648
+ * conn.set_error_context_visibility( context_visibility ) -> Integer
2649
+ *
2650
+ * Sets connection's context display mode to _context_visibility_ and returns
2651
+ * the previous setting. Available settings are:
2652
+ * * PQSHOW_CONTEXT_NEVER
2653
+ * * PQSHOW_CONTEXT_ERRORS
2654
+ * * PQSHOW_CONTEXT_ALWAYS
2655
+ *
2656
+ * This mode controls whether the CONTEXT field is included in messages (unless the verbosity setting is TERSE, in which case CONTEXT is never shown).
2657
+ * The NEVER mode never includes CONTEXT, while ALWAYS always includes it if available.
2658
+ * In ERRORS mode (the default), CONTEXT fields are included only for error messages, not for notices and warnings.
2659
+ *
2660
+ * Changing this mode does not affect the messages available from already-existing PG::Result objects, only subsequently-created ones.
2661
+ * (But see PG::Result#verbose_error_message if you want to print a previous error with a different display mode.)
2662
+ *
2663
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-control.html#LIBPQ-PQSETERRORCONTEXTVISIBILITY].
2664
+ *
2665
+ * Available since PostgreSQL-9.6
2666
+ */
2667
+ static VALUE
2668
+ pgconn_set_error_context_visibility(VALUE self, VALUE in_context_visibility)
2669
+ {
2670
+ PGconn *conn = pg_get_pgconn(self);
2671
+ PGContextVisibility context_visibility = NUM2INT(in_context_visibility);
2672
+ return INT2FIX(PQsetErrorContextVisibility(conn, context_visibility));
2673
+ }
2674
+ #endif
2675
+
2743
2676
  /*
2744
2677
  * call-seq:
2745
2678
  * conn.trace( stream ) -> nil
@@ -2758,7 +2691,7 @@ pgconn_trace(VALUE self, VALUE stream)
2758
2691
  VALUE new_file;
2759
2692
  t_pg_connection *this = pg_get_connection_safe( self );
2760
2693
 
2761
- if(rb_respond_to(stream,rb_intern("fileno")) == Qfalse)
2694
+ if(!rb_respond_to(stream,rb_intern("fileno")))
2762
2695
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2763
2696
 
2764
2697
  fileno = rb_funcall(stream, rb_intern("fileno"), 0);
@@ -2891,8 +2824,8 @@ notice_processor_proxy(void *arg, const char *message)
2891
2824
  t_pg_connection *this = pg_get_connection( self );
2892
2825
 
2893
2826
  if (this->notice_receiver != Qnil) {
2894
- VALUE message_str = rb_tainted_str_new2(message);
2895
- PG_ENCODING_SET_NOCHECK( message_str, ENCODING_GET(self) );
2827
+ VALUE message_str = rb_str_new2(message);
2828
+ PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2896
2829
  rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2897
2830
  }
2898
2831
  return;
@@ -2902,7 +2835,7 @@ notice_processor_proxy(void *arg, const char *message)
2902
2835
  * call-seq:
2903
2836
  * conn.set_notice_processor {|message| ... } -> Proc
2904
2837
  *
2905
- * See #set_notice_receiver for the desription of what this and the
2838
+ * See #set_notice_receiver for the description of what this and the
2906
2839
  * notice_processor methods do.
2907
2840
  *
2908
2841
  * This function takes a new block to act as the notice processor and returns
@@ -2950,83 +2883,40 @@ static VALUE
2950
2883
  pgconn_get_client_encoding(VALUE self)
2951
2884
  {
2952
2885
  char *encoding = (char *)pg_encoding_to_char(PQclientEncoding(pg_get_pgconn(self)));
2953
- return rb_tainted_str_new2(encoding);
2886
+ return rb_str_new2(encoding);
2954
2887
  }
2955
2888
 
2956
2889
 
2957
2890
  /*
2958
2891
  * call-seq:
2959
- * conn.set_client_encoding( encoding )
2892
+ * conn.sync_set_client_encoding( encoding )
2960
2893
  *
2961
- * Sets the client encoding to the _encoding_ String.
2894
+ * This function has the same behavior as #async_set_client_encoding, but is implemented using the synchronous command processing API of libpq.
2895
+ * See #async_exec for the differences between the two API variants.
2896
+ * It's not recommended to use explicit sync or async variants but #set_client_encoding instead, unless you have a good reason to do so.
2962
2897
  */
2963
2898
  static VALUE
2964
- pgconn_set_client_encoding(VALUE self, VALUE str)
2899
+ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2965
2900
  {
2966
2901
  PGconn *conn = pg_get_pgconn( self );
2967
2902
 
2968
2903
  Check_Type(str, T_STRING);
2969
2904
 
2970
2905
  if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2971
- rb_raise(rb_ePGerror, "invalid encoding name: %s",StringValueCStr(str));
2906
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2972
2907
  }
2973
- #ifdef M17N_SUPPORTED
2974
2908
  pgconn_set_internal_encoding_index( self );
2975
- #endif
2976
2909
 
2977
2910
  return Qnil;
2978
2911
  }
2979
2912
 
2913
+
2980
2914
  /*
2981
2915
  * call-seq:
2982
- * conn.transaction { |conn| ... } -> result of the block
2983
- *
2984
- * Executes a +BEGIN+ at the start of the block,
2985
- * and a +COMMIT+ at the end of the block, or
2986
- * +ROLLBACK+ if any exception occurs.
2987
- */
2988
- static VALUE
2989
- pgconn_transaction(VALUE self)
2990
- {
2991
- PGconn *conn = pg_get_pgconn(self);
2992
- PGresult *result;
2993
- VALUE rb_pgresult;
2994
- VALUE block_result = Qnil;
2995
- int status;
2996
-
2997
- if (rb_block_given_p()) {
2998
- result = gvl_PQexec(conn, "BEGIN");
2999
- rb_pgresult = pg_new_result(result, self);
3000
- pg_result_check(rb_pgresult);
3001
- block_result = rb_protect(rb_yield, self, &status);
3002
- if(status == 0) {
3003
- result = gvl_PQexec(conn, "COMMIT");
3004
- rb_pgresult = pg_new_result(result, self);
3005
- pg_result_check(rb_pgresult);
3006
- }
3007
- else {
3008
- /* exception occurred, ROLLBACK and re-raise */
3009
- result = gvl_PQexec(conn, "ROLLBACK");
3010
- rb_pgresult = pg_new_result(result, self);
3011
- pg_result_check(rb_pgresult);
3012
- rb_jump_tag(status);
3013
- }
3014
-
3015
- }
3016
- else {
3017
- /* no block supplied? */
3018
- rb_raise(rb_eArgError, "Must supply block for PG::Connection#transaction");
3019
- }
3020
- return block_result;
3021
- }
3022
-
3023
-
3024
- /*
3025
- * call-seq:
3026
- * conn.quote_ident( str ) -> String
3027
- * conn.quote_ident( array ) -> String
3028
- * PG::Connection.quote_ident( str ) -> String
3029
- * PG::Connection.quote_ident( array ) -> String
2916
+ * conn.quote_ident( str ) -> String
2917
+ * conn.quote_ident( array ) -> String
2918
+ * PG::Connection.quote_ident( str ) -> String
2919
+ * PG::Connection.quote_ident( array ) -> String
3030
2920
  *
3031
2921
  * Returns a string that is safe for inclusion in a SQL query as an
3032
2922
  * identifier. Note: this is not a quote function for values, but for
@@ -3064,14 +2954,12 @@ pgconn_s_quote_ident(VALUE self, VALUE str_or_array)
3064
2954
  int enc_idx;
3065
2955
 
3066
2956
  if( rb_obj_is_kind_of(self, rb_cPGconn) ){
3067
- enc_idx = ENCODING_GET( self );
2957
+ enc_idx = pg_get_connection(self)->enc_idx;
3068
2958
  }else{
3069
2959
  enc_idx = RB_TYPE_P(str_or_array, T_STRING) ? ENCODING_GET( str_or_array ) : rb_ascii8bit_encindex();
3070
2960
  }
3071
2961
  pg_text_enc_identifier(NULL, str_or_array, NULL, &ret, enc_idx);
3072
2962
 
3073
- OBJ_INFECT(ret, str_or_array);
3074
-
3075
2963
  return ret;
3076
2964
  }
3077
2965
 
@@ -3085,110 +2973,442 @@ get_result_readable(PGconn *conn)
3085
2973
 
3086
2974
  /*
3087
2975
  * call-seq:
3088
- * conn.block( [ timeout ] ) -> Boolean
2976
+ * conn.block( [ timeout ] ) -> Boolean
2977
+ *
2978
+ * Blocks until the server is no longer busy, or until the
2979
+ * optional _timeout_ is reached, whichever comes first.
2980
+ * _timeout_ is measured in seconds and can be fractional.
2981
+ *
2982
+ * Returns +false+ if _timeout_ is reached, +true+ otherwise.
2983
+ *
2984
+ * If +true+ is returned, +conn.is_busy+ will return +false+
2985
+ * and +conn.get_result+ will not block.
2986
+ */
2987
+ static VALUE
2988
+ pgconn_block( int argc, VALUE *argv, VALUE self ) {
2989
+ struct timeval timeout;
2990
+ struct timeval *ptimeout = NULL;
2991
+ VALUE timeout_in;
2992
+ double timeout_sec;
2993
+ void *ret;
2994
+
2995
+ if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
2996
+ timeout_sec = NUM2DBL( timeout_in );
2997
+ timeout.tv_sec = (time_t)timeout_sec;
2998
+ timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
2999
+ ptimeout = &timeout;
3000
+ }
3001
+
3002
+ ret = wait_socket_readable( self, ptimeout, get_result_readable);
3003
+
3004
+ if( !ret )
3005
+ return Qfalse;
3006
+
3007
+ return Qtrue;
3008
+ }
3009
+
3010
+
3011
+ /*
3012
+ * call-seq:
3013
+ * conn.sync_get_last_result( ) -> PG::Result
3014
+ *
3015
+ * This function has the same behavior as #async_get_last_result, but is implemented using the synchronous command processing API of libpq.
3016
+ * See #async_exec for the differences between the two API variants.
3017
+ * It's not recommended to use explicit sync or async variants but #get_last_result instead, unless you have a good reason to do so.
3018
+ */
3019
+ static VALUE
3020
+ pgconn_sync_get_last_result(VALUE self)
3021
+ {
3022
+ PGconn *conn = pg_get_pgconn(self);
3023
+ VALUE rb_pgresult = Qnil;
3024
+ PGresult *cur, *prev;
3025
+
3026
+
3027
+ cur = prev = NULL;
3028
+ while ((cur = gvl_PQgetResult(conn)) != NULL) {
3029
+ int status;
3030
+
3031
+ if (prev) PQclear(prev);
3032
+ prev = cur;
3033
+
3034
+ status = PQresultStatus(cur);
3035
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3036
+ break;
3037
+ }
3038
+
3039
+ if (prev) {
3040
+ rb_pgresult = pg_new_result( prev, self );
3041
+ pg_result_check(rb_pgresult);
3042
+ }
3043
+
3044
+ return rb_pgresult;
3045
+ }
3046
+
3047
+ /*
3048
+ * call-seq:
3049
+ * conn.get_last_result( ) -> PG::Result
3050
+ *
3051
+ * This function retrieves all available results
3052
+ * on the current connection (from previously issued
3053
+ * asynchronous commands like +send_query()+) and
3054
+ * returns the last non-NULL result, or +nil+ if no
3055
+ * results are available.
3056
+ *
3057
+ * If the last result contains a bad result_status, an
3058
+ * appropriate exception is raised.
3059
+ *
3060
+ * This function is similar to #get_result
3061
+ * except that it is designed to get one and only
3062
+ * one result and that it checks the result state.
3063
+ */
3064
+ static VALUE
3065
+ pgconn_async_get_last_result(VALUE self)
3066
+ {
3067
+ PGconn *conn = pg_get_pgconn(self);
3068
+ VALUE rb_pgresult = Qnil;
3069
+ PGresult *cur, *prev;
3070
+
3071
+ cur = prev = NULL;
3072
+ for(;;) {
3073
+ int status;
3074
+
3075
+ pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3076
+
3077
+ cur = gvl_PQgetResult(conn);
3078
+ if (cur == NULL)
3079
+ break;
3080
+
3081
+ if (prev) PQclear(prev);
3082
+ prev = cur;
3083
+
3084
+ status = PQresultStatus(cur);
3085
+ if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN || status == PGRES_COPY_BOTH)
3086
+ break;
3087
+ }
3088
+
3089
+ if (prev) {
3090
+ rb_pgresult = pg_new_result( prev, self );
3091
+ pg_result_check(rb_pgresult);
3092
+ }
3093
+
3094
+ return rb_pgresult;
3095
+ }
3096
+
3097
+ /*
3098
+ * call-seq:
3099
+ * conn.discard_results()
3100
+ *
3101
+ * Silently discard any prior query result that application didn't eat.
3102
+ * This is done prior of Connection#exec and sibling methods and can
3103
+ * be called explicitly when using the async API.
3104
+ */
3105
+ static VALUE
3106
+ pgconn_discard_results(VALUE self)
3107
+ {
3108
+ PGconn *conn = pg_get_pgconn(self);
3109
+ VALUE socket_io;
3110
+
3111
+ if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3112
+ return Qnil;
3113
+ }
3114
+
3115
+ socket_io = pgconn_socket_io(self);
3116
+
3117
+ for(;;) {
3118
+ PGresult *cur;
3119
+ int status;
3120
+
3121
+ /* pgconn_block() raises an exception in case of errors.
3122
+ * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3123
+ */
3124
+ while( gvl_PQisBusy(conn) ){
3125
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3126
+ if ( PQconsumeInput(conn) == 0 ) {
3127
+ pgconn_close_socket_io(self);
3128
+ return Qfalse;
3129
+ }
3130
+ }
3131
+
3132
+ cur = gvl_PQgetResult(conn);
3133
+ if( cur == NULL) break;
3134
+
3135
+ status = PQresultStatus(cur);
3136
+ PQclear(cur);
3137
+ if (status == PGRES_COPY_IN){
3138
+ gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
3139
+ }
3140
+ if (status == PGRES_COPY_OUT){
3141
+ for(;;) {
3142
+ char *buffer = NULL;
3143
+ int st = gvl_PQgetCopyData(conn, &buffer, 1);
3144
+ if( st == 0 ) {
3145
+ /* would block -> wait for readable data */
3146
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3147
+ if ( PQconsumeInput(conn) == 0 ) {
3148
+ pgconn_close_socket_io(self);
3149
+ return Qfalse;
3150
+ }
3151
+ } else if( st > 0 ) {
3152
+ /* some data retrieved -> discard it */
3153
+ PQfreemem(buffer);
3154
+ } else {
3155
+ /* no more data */
3156
+ break;
3157
+ }
3158
+ }
3159
+ }
3160
+ }
3161
+
3162
+ return Qtrue;
3163
+ }
3164
+
3165
+ /*
3166
+ * call-seq:
3167
+ * conn.exec(sql) -> PG::Result
3168
+ * conn.exec(sql) {|pg_result| block }
3169
+ *
3170
+ * Sends SQL query request specified by _sql_ to PostgreSQL.
3171
+ * On success, it returns a PG::Result instance with all result rows and columns.
3172
+ * On failure, it raises a PG::Error.
3173
+ *
3174
+ * For backward compatibility, if you pass more than one parameter to this method,
3175
+ * it will call #exec_params for you. New code should explicitly use #exec_params if
3176
+ * argument placeholders are used.
3177
+ *
3178
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3179
+ * and the PG::Result object will automatically be cleared when the block terminates.
3180
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3181
+ *
3182
+ * #exec is an alias for #async_exec which is almost identical to #sync_exec .
3183
+ * #sync_exec is implemented on the simpler synchronous command processing API of libpq, whereas
3184
+ * #async_exec is implemented on the asynchronous API and on ruby's IO mechanisms.
3185
+ * Only #async_exec is compatible to <tt>Fiber.scheduler</tt> based asynchronous IO processing introduced in ruby-3.0.
3186
+ * Both methods ensure that other threads can process while waiting for the server to
3187
+ * complete the request, but #sync_exec blocks all signals to be processed until the query is finished.
3188
+ * This is most notably visible by a delayed reaction to Control+C.
3189
+ * It's not recommended to use explicit sync or async variants but #exec instead, unless you have a good reason to do so.
3190
+ *
3191
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXEC].
3192
+ */
3193
+ static VALUE
3194
+ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3195
+ {
3196
+ VALUE rb_pgresult = Qnil;
3197
+
3198
+ pgconn_discard_results( self );
3199
+ pgconn_send_query( argc, argv, self );
3200
+ rb_pgresult = pgconn_async_get_last_result( self );
3201
+
3202
+ if ( rb_block_given_p() ) {
3203
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3204
+ }
3205
+ return rb_pgresult;
3206
+ }
3207
+
3208
+
3209
+ /*
3210
+ * call-seq:
3211
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) -> nil
3212
+ * conn.exec_params(sql, params [, result_format [, type_map ]] ) {|pg_result| block }
3213
+ *
3214
+ * Sends SQL query request specified by +sql+ to PostgreSQL using placeholders
3215
+ * for parameters.
3216
+ *
3217
+ * Returns a PG::Result instance on success. On failure, it raises a PG::Error.
3218
+ *
3219
+ * +params+ is an array of the bind parameters for the SQL query.
3220
+ * Each element of the +params+ array may be either:
3221
+ * a hash of the form:
3222
+ * {:value => String (value of bind parameter)
3223
+ * :type => Integer (oid of type of bind parameter)
3224
+ * :format => Integer (0 for text, 1 for binary)
3225
+ * }
3226
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3227
+ * { :value => <string value>, :type => 0, :format => 0 }
3228
+ *
3229
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3230
+ * inside the SQL query. The 0th element of the +params+ array is bound
3231
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3232
+ *
3233
+ * If the types are not specified, they will be inferred by PostgreSQL.
3234
+ * Instead of specifying type oids, it's recommended to simply add
3235
+ * explicit casts in the query to ensure that the right type is used.
3236
+ *
3237
+ * For example: "SELECT $1::int"
3238
+ *
3239
+ * The optional +result_format+ should be 0 for text results, 1
3240
+ * for binary.
3241
+ *
3242
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3243
+ * This will type cast the params from various Ruby types before transmission
3244
+ * based on the encoders defined by the type map. When a type encoder is used
3245
+ * the format and oid of a given bind parameter are retrieved from the encoder
3246
+ * instead out of the hash form described above.
3247
+ *
3248
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3249
+ * and the PG::Result object will automatically be cleared when the block terminates.
3250
+ * In this instance, <code>conn.exec</code> returns the value of the block.
3251
+ *
3252
+ * The primary advantage of #exec_params over #exec is that parameter values can be separated from the command string, thus avoiding the need for tedious and error-prone quoting and escaping.
3253
+ * Unlike #exec, #exec_params allows at most one SQL command in the given string.
3254
+ * (There can be semicolons in it, but not more than one nonempty command.)
3255
+ * This is a limitation of the underlying protocol, but has some usefulness as an extra defense against SQL-injection attacks.
3256
+ *
3257
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPARAMS].
3258
+ */
3259
+ static VALUE
3260
+ pgconn_async_exec_params(int argc, VALUE *argv, VALUE self)
3261
+ {
3262
+ VALUE rb_pgresult = Qnil;
3263
+
3264
+ pgconn_discard_results( self );
3265
+ /* If called with no or nil parameters, use PQsendQuery for compatibility */
3266
+ if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
3267
+ pg_deprecated(3, ("forwarding async_exec_params to async_exec is deprecated"));
3268
+ pgconn_send_query( argc, argv, self );
3269
+ } else {
3270
+ pgconn_send_query_params( argc, argv, self );
3271
+ }
3272
+ rb_pgresult = pgconn_async_get_last_result( self );
3273
+
3274
+ if ( rb_block_given_p() ) {
3275
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3276
+ }
3277
+ return rb_pgresult;
3278
+ }
3279
+
3280
+
3281
+ /*
3282
+ * call-seq:
3283
+ * conn.prepare(stmt_name, sql [, param_types ] ) -> PG::Result
3284
+ *
3285
+ * Prepares statement _sql_ with name _name_ to be executed later.
3286
+ * Returns a PG::Result instance on success.
3287
+ * On failure, it raises a PG::Error.
3288
+ *
3289
+ * +param_types+ is an optional parameter to specify the Oids of the
3290
+ * types of the parameters.
3291
+ *
3292
+ * If the types are not specified, they will be inferred by PostgreSQL.
3293
+ * Instead of specifying type oids, it's recommended to simply add
3294
+ * explicit casts in the query to ensure that the right type is used.
3295
+ *
3296
+ * For example: "SELECT $1::int"
3297
+ *
3298
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3299
+ * inside the SQL query.
3300
+ *
3301
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQPREPARE].
3302
+ */
3303
+ static VALUE
3304
+ pgconn_async_prepare(int argc, VALUE *argv, VALUE self)
3305
+ {
3306
+ VALUE rb_pgresult = Qnil;
3307
+
3308
+ pgconn_discard_results( self );
3309
+ pgconn_send_prepare( argc, argv, self );
3310
+ rb_pgresult = pgconn_async_get_last_result( self );
3311
+
3312
+ if ( rb_block_given_p() ) {
3313
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3314
+ }
3315
+ return rb_pgresult;
3316
+ }
3317
+
3318
+
3319
+ /*
3320
+ * call-seq:
3321
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) -> PG::Result
3322
+ * conn.exec_prepared(statement_name [, params, result_format[, type_map]] ) {|pg_result| block }
3089
3323
  *
3090
- * Blocks until the server is no longer busy, or until the
3091
- * optional _timeout_ is reached, whichever comes first.
3092
- * _timeout_ is measured in seconds and can be fractional.
3324
+ * Execute prepared named statement specified by _statement_name_.
3325
+ * Returns a PG::Result instance on success.
3326
+ * On failure, it raises a PG::Error.
3093
3327
  *
3094
- * Returns +false+ if _timeout_ is reached, +true+ otherwise.
3328
+ * +params+ is an array of the optional bind parameters for the
3329
+ * SQL query. Each element of the +params+ array may be either:
3330
+ * a hash of the form:
3331
+ * {:value => String (value of bind parameter)
3332
+ * :format => Integer (0 for text, 1 for binary)
3333
+ * }
3334
+ * or, it may be a String. If it is a string, that is equivalent to the hash:
3335
+ * { :value => <string value>, :format => 0 }
3095
3336
  *
3096
- * If +true+ is returned, +conn.is_busy+ will return +false+
3097
- * and +conn.get_result+ will not block.
3337
+ * PostgreSQL bind parameters are represented as $1, $2, $3, etc.,
3338
+ * inside the SQL query. The 0th element of the +params+ array is bound
3339
+ * to $1, the 1st element is bound to $2, etc. +nil+ is treated as +NULL+.
3340
+ *
3341
+ * The optional +result_format+ should be 0 for text results, 1
3342
+ * for binary.
3343
+ *
3344
+ * +type_map+ can be a PG::TypeMap derivation (such as PG::BasicTypeMapForQueries).
3345
+ * This will type cast the params from various Ruby types before transmission
3346
+ * based on the encoders defined by the type map. When a type encoder is used
3347
+ * the format and oid of a given bind parameter are retrieved from the encoder
3348
+ * instead out of the hash form described above.
3349
+ *
3350
+ * If the optional code block is given, it will be passed <i>result</i> as an argument,
3351
+ * and the PG::Result object will automatically be cleared when the block terminates.
3352
+ * In this instance, <code>conn.exec_prepared</code> returns the value of the block.
3353
+ *
3354
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQEXECPREPARED].
3098
3355
  */
3099
3356
  static VALUE
3100
- pgconn_block( int argc, VALUE *argv, VALUE self ) {
3101
- PGconn *conn = pg_get_pgconn( self );
3102
-
3103
- /* If WIN32 and Ruby 1.9 do not use rb_thread_select() which sometimes hangs
3104
- * and does not wait (nor sleep) any time even if timeout is given.
3105
- * Instead use the Winsock events and rb_w32_wait_events(). */
3357
+ pgconn_async_exec_prepared(int argc, VALUE *argv, VALUE self)
3358
+ {
3359
+ VALUE rb_pgresult = Qnil;
3106
3360
 
3107
- struct timeval timeout;
3108
- struct timeval *ptimeout = NULL;
3109
- VALUE timeout_in;
3110
- double timeout_sec;
3111
- void *ret;
3361
+ pgconn_discard_results( self );
3362
+ pgconn_send_query_prepared( argc, argv, self );
3363
+ rb_pgresult = pgconn_async_get_last_result( self );
3112
3364
 
3113
- if ( rb_scan_args(argc, argv, "01", &timeout_in) == 1 ) {
3114
- timeout_sec = NUM2DBL( timeout_in );
3115
- timeout.tv_sec = (time_t)timeout_sec;
3116
- timeout.tv_usec = (suseconds_t)((timeout_sec - (long)timeout_sec) * 1e6);
3117
- ptimeout = &timeout;
3365
+ if ( rb_block_given_p() ) {
3366
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3118
3367
  }
3119
-
3120
- ret = wait_socket_readable( conn, ptimeout, get_result_readable);
3121
-
3122
- if( !ret )
3123
- return Qfalse;
3124
-
3125
- return Qtrue;
3368
+ return rb_pgresult;
3126
3369
  }
3127
3370
 
3128
3371
 
3129
3372
  /*
3130
3373
  * call-seq:
3131
- * conn.get_last_result( ) -> PG::Result
3374
+ * conn.describe_portal( portal_name ) -> PG::Result
3132
3375
  *
3133
- * This function retrieves all available results
3134
- * on the current connection (from previously issued
3135
- * asynchronous commands like +send_query()+) and
3136
- * returns the last non-NULL result, or +nil+ if no
3137
- * results are available.
3376
+ * Retrieve information about the portal _portal_name_.
3138
3377
  *
3139
- * This function is similar to #get_result
3140
- * except that it is designed to get one and only
3141
- * one result.
3378
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPORTAL].
3142
3379
  */
3143
3380
  static VALUE
3144
- pgconn_get_last_result(VALUE self)
3381
+ pgconn_async_describe_portal(VALUE self, VALUE portal)
3145
3382
  {
3146
- PGconn *conn = pg_get_pgconn(self);
3147
3383
  VALUE rb_pgresult = Qnil;
3148
- PGresult *cur, *prev;
3149
-
3150
-
3151
- cur = prev = NULL;
3152
- while ((cur = gvl_PQgetResult(conn)) != NULL) {
3153
- int status;
3154
3384
 
3155
- if (prev) PQclear(prev);
3156
- prev = cur;
3157
-
3158
- status = PQresultStatus(cur);
3159
- if (status == PGRES_COPY_OUT || status == PGRES_COPY_IN)
3160
- break;
3161
- }
3385
+ pgconn_discard_results( self );
3386
+ pgconn_send_describe_portal( self, portal );
3387
+ rb_pgresult = pgconn_async_get_last_result( self );
3162
3388
 
3163
- if (prev) {
3164
- rb_pgresult = pg_new_result( prev, self );
3165
- pg_result_check(rb_pgresult);
3389
+ if ( rb_block_given_p() ) {
3390
+ return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
3166
3391
  }
3167
-
3168
3392
  return rb_pgresult;
3169
3393
  }
3170
3394
 
3395
+
3171
3396
  /*
3172
3397
  * call-seq:
3173
- * conn.async_exec(sql [, params, result_format ] ) -> PG::Result
3174
- * conn.async_exec(sql [, params, result_format ] ) {|pg_result| block }
3398
+ * conn.describe_prepared( statement_name ) -> PG::Result
3175
3399
  *
3176
- * This function has the same behavior as #exec,
3177
- * but is implemented using the asynchronous command
3178
- * processing API of libpq.
3400
+ * Retrieve information about the prepared statement _statement_name_.
3401
+ *
3402
+ * See also corresponding {libpq function}[https://www.postgresql.org/docs/current/libpq-exec.html#LIBPQ-PQDESCRIBEPREPARED].
3179
3403
  */
3180
3404
  static VALUE
3181
- pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3405
+ pgconn_async_describe_prepared(VALUE self, VALUE stmt_name)
3182
3406
  {
3183
3407
  VALUE rb_pgresult = Qnil;
3184
3408
 
3185
- /* remove any remaining results from the queue */
3186
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3187
- pgconn_get_last_result( self );
3188
-
3189
- pgconn_send_query( argc, argv, self );
3190
- pgconn_block( 0, NULL, self );
3191
- rb_pgresult = pgconn_get_last_result( self );
3409
+ pgconn_discard_results( self );
3410
+ pgconn_send_describe_prepared( self, stmt_name );
3411
+ rb_pgresult = pgconn_async_get_last_result( self );
3192
3412
 
3193
3413
  if ( rb_block_given_p() ) {
3194
3414
  return rb_ensure( rb_yield, rb_pgresult, pg_result_clear, rb_pgresult );
@@ -3198,14 +3418,13 @@ pgconn_async_exec(int argc, VALUE *argv, VALUE self)
3198
3418
 
3199
3419
 
3200
3420
  #ifdef HAVE_PQSSLATTRIBUTE
3201
- /* Since PostgreSQL-9.5: */
3202
-
3203
3421
  /*
3204
3422
  * call-seq:
3205
3423
  * conn.ssl_in_use? -> Boolean
3206
3424
  *
3207
- * Returns +true+ if the connection uses SSL, +false+ if not.
3425
+ * Returns +true+ if the connection uses SSL/TLS, +false+ if not.
3208
3426
  *
3427
+ * Available since PostgreSQL-9.5
3209
3428
  */
3210
3429
  static VALUE
3211
3430
  pgconn_ssl_in_use(VALUE self)
@@ -3237,7 +3456,9 @@ pgconn_ssl_in_use(VALUE self)
3237
3456
  * If SSL compression is in use, returns the name of the compression algorithm, or "on" if compression is used but the algorithm is not known. If compression is not in use, returns "off".
3238
3457
  *
3239
3458
  *
3240
- * See also #ssl_attribute_names and http://www.postgresql.org/docs/current/interactive/libpq-status.html#LIBPQ-PQSSLATTRIBUTE
3459
+ * See also #ssl_attribute_names and the {corresponding libpq function}[https://www.postgresql.org/docs/current/libpq-status.html#LIBPQ-PQSSLATTRIBUTE].
3460
+ *
3461
+ * Available since PostgreSQL-9.5
3241
3462
  */
3242
3463
  static VALUE
3243
3464
  pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
@@ -3256,6 +3477,7 @@ pgconn_ssl_attribute(VALUE self, VALUE attribute_name)
3256
3477
  *
3257
3478
  * See also #ssl_attribute
3258
3479
  *
3480
+ * Available since PostgreSQL-9.5
3259
3481
  */
3260
3482
  static VALUE
3261
3483
  pgconn_ssl_attribute_names(VALUE self)
@@ -3274,6 +3496,126 @@ pgconn_ssl_attribute_names(VALUE self)
3274
3496
  #endif
3275
3497
 
3276
3498
 
3499
+ #ifdef HAVE_PQENTERPIPELINEMODE
3500
+ /*
3501
+ * call-seq:
3502
+ * conn.pipeline_status -> Integer
3503
+ *
3504
+ * Returns the current pipeline mode status of the libpq connection.
3505
+ *
3506
+ * PQpipelineStatus can return one of the following values:
3507
+ *
3508
+ * * PQ_PIPELINE_ON - The libpq connection is in pipeline mode.
3509
+ * * PQ_PIPELINE_OFF - The libpq connection is not in pipeline mode.
3510
+ * * PQ_PIPELINE_ABORTED - The libpq connection is in pipeline mode and an error occurred while processing the current pipeline.
3511
+ * The aborted flag is cleared when PQgetResult returns a result of type PGRES_PIPELINE_SYNC.
3512
+ *
3513
+ * Available since PostgreSQL-14
3514
+ */
3515
+ static VALUE
3516
+ pgconn_pipeline_status(VALUE self)
3517
+ {
3518
+ int res = PQpipelineStatus(pg_get_pgconn(self));
3519
+ return INT2FIX(res);
3520
+ }
3521
+
3522
+
3523
+ /*
3524
+ * call-seq:
3525
+ * conn.enter_pipeline_mode -> nil
3526
+ *
3527
+ * Causes a connection to enter pipeline mode if it is currently idle or already in pipeline mode.
3528
+ *
3529
+ * Raises PG::Error and has no effect if the connection is not currently idle, i.e., it has a result ready, or it is waiting for more input from the server, etc.
3530
+ * This function does not actually send anything to the server, it just changes the libpq connection state.
3531
+ *
3532
+ * Available since PostgreSQL-14
3533
+ */
3534
+ static VALUE
3535
+ pgconn_enter_pipeline_mode(VALUE self)
3536
+ {
3537
+ PGconn *conn = pg_get_pgconn(self);
3538
+ int res = PQenterPipelineMode(conn);
3539
+ if( res == 1 ) {
3540
+ return Qnil;
3541
+ } else {
3542
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3543
+ }
3544
+ }
3545
+
3546
+ /*
3547
+ * call-seq:
3548
+ * conn.exit_pipeline_mode -> nil
3549
+ *
3550
+ * Causes a connection to exit pipeline mode if it is currently in pipeline mode with an empty queue and no pending results.
3551
+ *
3552
+ * Takes no action if not in pipeline mode.
3553
+ * Raises PG::Error if the current statement isn't finished processing, or PQgetResult has not been called to collect results from all previously sent query.
3554
+ *
3555
+ * Available since PostgreSQL-14
3556
+ */
3557
+ static VALUE
3558
+ pgconn_exit_pipeline_mode(VALUE self)
3559
+ {
3560
+ PGconn *conn = pg_get_pgconn(self);
3561
+ int res = PQexitPipelineMode(conn);
3562
+ if( res == 1 ) {
3563
+ return Qnil;
3564
+ } else {
3565
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3566
+ }
3567
+ }
3568
+
3569
+
3570
+ /*
3571
+ * call-seq:
3572
+ * conn.pipeline_sync -> nil
3573
+ *
3574
+ * Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
3575
+ * This serves as the delimiter of an implicit transaction and an error recovery point; see Section 34.5.1.3 of the PostgreSQL documentation.
3576
+ *
3577
+ * Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
3578
+ *
3579
+ * Available since PostgreSQL-14
3580
+ */
3581
+ static VALUE
3582
+ pgconn_pipeline_sync(VALUE self)
3583
+ {
3584
+ PGconn *conn = pg_get_pgconn(self);
3585
+ int res = PQpipelineSync(conn);
3586
+ if( res == 1 ) {
3587
+ return Qnil;
3588
+ } else {
3589
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3590
+ }
3591
+ }
3592
+
3593
+ /*
3594
+ * call-seq:
3595
+ * conn.pipeline_sync -> nil
3596
+ *
3597
+ * Sends a request for the server to flush its output buffer.
3598
+ *
3599
+ * The server flushes its output buffer automatically as a result of Connection#pipeline_sync being called, or on any request when not in pipeline mode.
3600
+ * This function is useful to cause the server to flush its output buffer in pipeline mode without establishing a synchronization point.
3601
+ * Note that the request is not itself flushed to the server automatically; use Connection#flush if necessary.
3602
+ *
3603
+ * Available since PostgreSQL-14
3604
+ */
3605
+ static VALUE
3606
+ pgconn_send_flush_request(VALUE self)
3607
+ {
3608
+ PGconn *conn = pg_get_pgconn(self);
3609
+ int res = PQsendFlushRequest(conn);
3610
+ if( res == 1 ) {
3611
+ return Qnil;
3612
+ } else {
3613
+ rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3614
+ }
3615
+ }
3616
+
3617
+ #endif
3618
+
3277
3619
  /**************************************************************************
3278
3620
  * LARGE OBJECT SUPPORT
3279
3621
  **************************************************************************/
@@ -3462,7 +3804,7 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3462
3804
  return Qnil;
3463
3805
  }
3464
3806
 
3465
- str = rb_tainted_str_new(buffer, ret);
3807
+ str = rb_str_new(buffer, ret);
3466
3808
  xfree(buffer);
3467
3809
 
3468
3810
  return str;
@@ -3566,14 +3908,15 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3566
3908
  }
3567
3909
 
3568
3910
 
3569
- #ifdef M17N_SUPPORTED
3570
-
3571
- void
3911
+ static void
3572
3912
  pgconn_set_internal_encoding_index( VALUE self )
3573
3913
  {
3574
- PGconn *conn = pg_get_pgconn(self);
3575
- rb_encoding *enc = pg_conn_enc_get( conn );
3576
- PG_ENCODING_SET_NOCHECK( self, rb_enc_to_index(enc));
3914
+ int enc_idx;
3915
+ t_pg_connection *this = pg_get_connection_safe( self );
3916
+ rb_encoding *enc = pg_conn_enc_get( this->pgconn );
3917
+ enc_idx = rb_enc_to_index(enc);
3918
+ if( enc_idx >= (1<<(PG_ENC_IDX_BITS-1)) ) rb_raise(rb_eArgError, "unsupported encoding index %d", enc_idx);
3919
+ this->enc_idx = enc_idx;
3577
3920
  }
3578
3921
 
3579
3922
  /*
@@ -3616,13 +3959,12 @@ static VALUE pgconn_external_encoding(VALUE self);
3616
3959
  static VALUE
3617
3960
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3618
3961
  {
3619
- VALUE enc_inspect;
3620
3962
  if (NIL_P(enc)) {
3621
- pgconn_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3963
+ pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3622
3964
  return enc;
3623
3965
  }
3624
3966
  else if ( TYPE(enc) == T_STRING && strcasecmp("JOHAB", StringValueCStr(enc)) == 0 ) {
3625
- pgconn_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3967
+ pgconn_sync_set_client_encoding(self, rb_usascii_str_new_cstr("JOHAB"));
3626
3968
  return enc;
3627
3969
  }
3628
3970
  else {
@@ -3637,11 +3979,6 @@ pgconn_internal_encoding_set(VALUE self, VALUE enc)
3637
3979
  pgconn_set_internal_encoding_index( self );
3638
3980
  return enc;
3639
3981
  }
3640
-
3641
- enc_inspect = rb_inspect(enc);
3642
- rb_raise( rb_ePGerror, "unknown encoding: %s", StringValueCStr(enc_inspect) );
3643
-
3644
- return Qnil;
3645
3982
  }
3646
3983
 
3647
3984
 
@@ -3660,42 +3997,55 @@ pgconn_external_encoding(VALUE self)
3660
3997
  rb_encoding *enc = NULL;
3661
3998
  const char *pg_encname = NULL;
3662
3999
 
3663
- /* Use cached value if found */
3664
- if ( RTEST(this->external_encoding) ) return this->external_encoding;
3665
-
3666
4000
  pg_encname = PQparameterStatus( this->pgconn, "server_encoding" );
3667
4001
  enc = pg_get_pg_encname_as_rb_encoding( pg_encname );
3668
- this->external_encoding = rb_enc_from_encoding( enc );
3669
-
3670
- return this->external_encoding;
4002
+ return rb_enc_from_encoding( enc );
3671
4003
  }
3672
4004
 
4005
+ /*
4006
+ * call-seq:
4007
+ * conn.set_client_encoding( encoding )
4008
+ *
4009
+ * Sets the client encoding to the _encoding_ String.
4010
+ */
4011
+ static VALUE
4012
+ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4013
+ {
4014
+ VALUE query_format, query;
4015
+
4016
+ Check_Type(encname, T_STRING);
4017
+ query_format = rb_str_new_cstr("set client_encoding to '%s'");
4018
+ query = rb_funcall(query_format, rb_intern("%"), 1, encname);
4019
+
4020
+ pgconn_async_exec(1, &query, self);
4021
+ pgconn_set_internal_encoding_index( self );
4022
+
4023
+ return Qnil;
4024
+ }
3673
4025
 
3674
4026
  static VALUE
3675
4027
  pgconn_set_client_encoding_async1( VALUE args )
3676
4028
  {
3677
4029
  VALUE self = ((VALUE*)args)[0];
3678
4030
  VALUE encname = ((VALUE*)args)[1];
3679
- VALUE query_format = rb_str_new_cstr("set client_encoding to '%s'");
3680
- VALUE query = rb_funcall(query_format, rb_intern("%"), 1, encname);
3681
-
3682
- pgconn_async_exec(1, &query, self);
4031
+ pgconn_async_set_client_encoding(self, encname);
3683
4032
  return 0;
3684
4033
  }
3685
4034
 
3686
4035
 
3687
4036
  static VALUE
3688
- pgconn_set_client_encoding_async2( VALUE arg )
4037
+ pgconn_set_client_encoding_async2( VALUE arg, VALUE ex )
3689
4038
  {
3690
4039
  UNUSED(arg);
4040
+ UNUSED(ex);
3691
4041
  return 1;
3692
4042
  }
3693
4043
 
3694
4044
 
3695
4045
  static VALUE
3696
- pgconn_set_client_encoding_async( VALUE self, const char *encname )
4046
+ pgconn_set_client_encoding_async( VALUE self, VALUE encname )
3697
4047
  {
3698
- VALUE args[] = { self, rb_str_new_cstr(encname) };
4048
+ VALUE args[] = { self, encname };
3699
4049
  return rb_rescue(pgconn_set_client_encoding_async1, (VALUE)&args, pgconn_set_client_encoding_async2, Qnil);
3700
4050
  }
3701
4051
 
@@ -3717,10 +4067,9 @@ pgconn_set_default_encoding( VALUE self )
3717
4067
 
3718
4068
  if (( enc = rb_default_internal_encoding() )) {
3719
4069
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
3720
- if ( pgconn_set_client_encoding_async(self, encname) != 0 )
3721
- rb_warn( "Failed to set the default_internal encoding to %s: '%s'",
4070
+ if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
4071
+ rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
3722
4072
  encname, PQerrorMessage(conn) );
3723
- pgconn_set_internal_encoding_index( self );
3724
4073
  return rb_enc_from_encoding( enc );
3725
4074
  } else {
3726
4075
  pgconn_set_internal_encoding_index( self );
@@ -3729,8 +4078,6 @@ pgconn_set_default_encoding( VALUE self )
3729
4078
  }
3730
4079
 
3731
4080
 
3732
- #endif /* M17N_SUPPORTED */
3733
-
3734
4081
  /*
3735
4082
  * call-seq:
3736
4083
  * res.type_map_for_queries = typemap
@@ -3744,12 +4091,12 @@ static VALUE
3744
4091
  pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
3745
4092
  {
3746
4093
  t_pg_connection *this = pg_get_connection( self );
4094
+ t_typemap *tm;
4095
+ UNUSED(tm);
4096
+
4097
+ /* Check type of method param */
4098
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3747
4099
 
3748
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3749
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3750
- rb_obj_classname( typemap ) );
3751
- }
3752
- Check_Type(typemap, T_DATA);
3753
4100
  this->type_map_for_queries = typemap;
3754
4101
 
3755
4102
  return typemap;
@@ -3784,12 +4131,10 @@ static VALUE
3784
4131
  pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
3785
4132
  {
3786
4133
  t_pg_connection *this = pg_get_connection( self );
4134
+ t_typemap *tm;
4135
+ UNUSED(tm);
3787
4136
 
3788
- if ( !rb_obj_is_kind_of(typemap, rb_cTypeMap) ) {
3789
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::TypeMap)",
3790
- rb_obj_classname( typemap ) );
3791
- }
3792
- Check_Type(typemap, T_DATA);
4137
+ TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
3793
4138
  this->type_map_for_results = typemap;
3794
4139
 
3795
4140
  return typemap;
@@ -3824,20 +4169,19 @@ pgconn_type_map_for_results_get(VALUE self)
3824
4169
  *
3825
4170
  */
3826
4171
  static VALUE
3827
- pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE typemap)
4172
+ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
3828
4173
  {
3829
4174
  t_pg_connection *this = pg_get_connection( self );
3830
4175
 
3831
- if( typemap != Qnil ){
3832
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
3833
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
3834
- rb_obj_classname( typemap ) );
3835
- }
3836
- Check_Type(typemap, T_DATA);
4176
+ if( encoder != Qnil ){
4177
+ t_pg_coder *co;
4178
+ UNUSED(co);
4179
+ /* Check argument type */
4180
+ TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
3837
4181
  }
3838
- this->encoder_for_put_copy_data = typemap;
4182
+ this->encoder_for_put_copy_data = encoder;
3839
4183
 
3840
- return typemap;
4184
+ return encoder;
3841
4185
  }
3842
4186
 
3843
4187
  /*
@@ -3873,20 +4217,19 @@ pgconn_encoder_for_put_copy_data_get(VALUE self)
3873
4217
  *
3874
4218
  */
3875
4219
  static VALUE
3876
- pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE typemap)
4220
+ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
3877
4221
  {
3878
4222
  t_pg_connection *this = pg_get_connection( self );
3879
4223
 
3880
- if( typemap != Qnil ){
3881
- if ( !rb_obj_is_kind_of(typemap, rb_cPG_Coder) ) {
3882
- rb_raise( rb_eTypeError, "wrong argument type %s (expected kind of PG::Coder)",
3883
- rb_obj_classname( typemap ) );
3884
- }
3885
- Check_Type(typemap, T_DATA);
4224
+ if( decoder != Qnil ){
4225
+ t_pg_coder *co;
4226
+ UNUSED(co);
4227
+ /* Check argument type */
4228
+ TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
3886
4229
  }
3887
- this->decoder_for_get_copy_data = typemap;
4230
+ this->decoder_for_get_copy_data = decoder;
3888
4231
 
3889
- return typemap;
4232
+ return decoder;
3890
4233
  }
3891
4234
 
3892
4235
  /*
@@ -3909,6 +4252,58 @@ pgconn_decoder_for_get_copy_data_get(VALUE self)
3909
4252
  return this->decoder_for_get_copy_data;
3910
4253
  }
3911
4254
 
4255
+ /*
4256
+ * call-seq:
4257
+ * conn.field_name_type = Symbol
4258
+ *
4259
+ * Set default type of field names of results retrieved by this connection.
4260
+ * It can be set to one of:
4261
+ * * +:string+ to use String based field names
4262
+ * * +:symbol+ to use Symbol based field names
4263
+ *
4264
+ * The default is +:string+ .
4265
+ *
4266
+ * Settings the type of field names affects only future results.
4267
+ *
4268
+ * See further description at PG::Result#field_name_type=
4269
+ *
4270
+ */
4271
+ static VALUE
4272
+ pgconn_field_name_type_set(VALUE self, VALUE sym)
4273
+ {
4274
+ t_pg_connection *this = pg_get_connection( self );
4275
+
4276
+ this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4277
+ if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4278
+ else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
4279
+ else if ( sym == sym_string );
4280
+ else rb_raise(rb_eArgError, "invalid argument %+"PRIsVALUE, sym);
4281
+
4282
+ return sym;
4283
+ }
4284
+
4285
+ /*
4286
+ * call-seq:
4287
+ * conn.field_name_type -> Symbol
4288
+ *
4289
+ * Get type of field names.
4290
+ *
4291
+ * See description at #field_name_type=
4292
+ */
4293
+ static VALUE
4294
+ pgconn_field_name_type_get(VALUE self)
4295
+ {
4296
+ t_pg_connection *this = pg_get_connection( self );
4297
+
4298
+ if( this->flags & PG_RESULT_FIELD_NAMES_SYMBOL ){
4299
+ return sym_symbol;
4300
+ } else if( this->flags & PG_RESULT_FIELD_NAMES_STATIC_SYMBOL ){
4301
+ return sym_static_symbol;
4302
+ } else {
4303
+ return sym_string;
4304
+ }
4305
+ }
4306
+
3912
4307
 
3913
4308
  /*
3914
4309
  * Document-class: PG::Connection
@@ -3917,20 +4312,22 @@ void
3917
4312
  init_pg_connection()
3918
4313
  {
3919
4314
  s_id_encode = rb_intern("encode");
4315
+ s_id_autoclose_set = rb_intern("autoclose=");
3920
4316
  sym_type = ID2SYM(rb_intern("type"));
3921
4317
  sym_format = ID2SYM(rb_intern("format"));
3922
4318
  sym_value = ID2SYM(rb_intern("value"));
4319
+ sym_string = ID2SYM(rb_intern("string"));
4320
+ sym_symbol = ID2SYM(rb_intern("symbol"));
4321
+ sym_static_symbol = ID2SYM(rb_intern("static_symbol"));
3923
4322
 
3924
4323
  rb_cPGconn = rb_define_class_under( rb_mPG, "Connection", rb_cObject );
4324
+ /* Help rdoc to known the Constants module */
4325
+ /* rb_mPGconstants = rb_define_module_under( rb_mPG, "Constants" ); */
3925
4326
  rb_include_module(rb_cPGconn, rb_mPGconstants);
3926
4327
 
3927
4328
  /****** PG::Connection CLASS METHODS ******/
3928
4329
  rb_define_alloc_func( rb_cPGconn, pgconn_s_allocate );
3929
4330
 
3930
- SINGLETON_ALIAS(rb_cPGconn, "connect", "new");
3931
- SINGLETON_ALIAS(rb_cPGconn, "open", "new");
3932
- SINGLETON_ALIAS(rb_cPGconn, "setdb", "new");
3933
- SINGLETON_ALIAS(rb_cPGconn, "setdblogin", "new");
3934
4331
  rb_define_singleton_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3935
4332
  SINGLETON_ALIAS(rb_cPGconn, "escape", "escape_string");
3936
4333
  rb_define_singleton_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
@@ -3939,16 +4336,14 @@ init_pg_connection()
3939
4336
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
3940
4337
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
3941
4338
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
3942
- #ifdef HAVE_PQPING
3943
- rb_define_singleton_method(rb_cPGconn, "ping", pgconn_s_ping, -1);
3944
- #endif
4339
+ rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4340
+ rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
3945
4341
 
3946
4342
  /****** PG::Connection INSTANCE METHODS: Connection Control ******/
3947
- rb_define_method(rb_cPGconn, "initialize", pgconn_init, -1);
3948
4343
  rb_define_method(rb_cPGconn, "connect_poll", pgconn_connect_poll, 0);
3949
4344
  rb_define_method(rb_cPGconn, "finish", pgconn_finish, 0);
3950
4345
  rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
3951
- rb_define_method(rb_cPGconn, "reset", pgconn_reset, 0);
4346
+ rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
3952
4347
  rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
3953
4348
  rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
3954
4349
  rb_define_alias(rb_cPGconn, "close", "finish");
@@ -3960,9 +4355,7 @@ init_pg_connection()
3960
4355
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
3961
4356
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
3962
4357
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
3963
- #ifdef HAVE_PQCONNINFO
3964
4358
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
3965
- #endif
3966
4359
  rb_define_method(rb_cPGconn, "options", pgconn_options, 0);
3967
4360
  rb_define_method(rb_cPGconn, "status", pgconn_status, 0);
3968
4361
  rb_define_method(rb_cPGconn, "transaction_status", pgconn_transaction_status, 0);
@@ -3971,64 +4364,78 @@ init_pg_connection()
3971
4364
  rb_define_method(rb_cPGconn, "server_version", pgconn_server_version, 0);
3972
4365
  rb_define_method(rb_cPGconn, "error_message", pgconn_error_message, 0);
3973
4366
  rb_define_method(rb_cPGconn, "socket", pgconn_socket, 0);
3974
- #if !defined(_WIN32) || defined(HAVE_RB_W32_WRAP_IO_HANDLE)
3975
4367
  rb_define_method(rb_cPGconn, "socket_io", pgconn_socket_io, 0);
3976
- #endif
3977
4368
  rb_define_method(rb_cPGconn, "backend_pid", pgconn_backend_pid, 0);
4369
+ rb_define_method(rb_cPGconn, "backend_key", pgconn_backend_key, 0);
3978
4370
  rb_define_method(rb_cPGconn, "connection_needs_password", pgconn_connection_needs_password, 0);
3979
4371
  rb_define_method(rb_cPGconn, "connection_used_password", pgconn_connection_used_password, 0);
3980
4372
  /* rb_define_method(rb_cPGconn, "getssl", pgconn_getssl, 0); */
3981
4373
 
3982
4374
  /****** PG::Connection INSTANCE METHODS: Command Execution ******/
3983
- rb_define_method(rb_cPGconn, "exec", pgconn_exec, -1);
3984
- rb_define_alias(rb_cPGconn, "query", "exec");
3985
- rb_define_method(rb_cPGconn, "exec_params", pgconn_exec_params, -1);
3986
- rb_define_method(rb_cPGconn, "prepare", pgconn_prepare, -1);
3987
- rb_define_method(rb_cPGconn, "exec_prepared", pgconn_exec_prepared, -1);
3988
- rb_define_method(rb_cPGconn, "describe_prepared", pgconn_describe_prepared, 1);
3989
- rb_define_method(rb_cPGconn, "describe_portal", pgconn_describe_portal, 1);
4375
+ rb_define_method(rb_cPGconn, "sync_exec", pgconn_sync_exec, -1);
4376
+ rb_define_method(rb_cPGconn, "sync_exec_params", pgconn_sync_exec_params, -1);
4377
+ rb_define_method(rb_cPGconn, "sync_prepare", pgconn_sync_prepare, -1);
4378
+ rb_define_method(rb_cPGconn, "sync_exec_prepared", pgconn_sync_exec_prepared, -1);
4379
+ rb_define_method(rb_cPGconn, "sync_describe_prepared", pgconn_sync_describe_prepared, 1);
4380
+ rb_define_method(rb_cPGconn, "sync_describe_portal", pgconn_sync_describe_portal, 1);
4381
+
4382
+ rb_define_method(rb_cPGconn, "exec", pgconn_async_exec, -1);
4383
+ rb_define_method(rb_cPGconn, "exec_params", pgconn_async_exec_params, -1);
4384
+ rb_define_method(rb_cPGconn, "prepare", pgconn_async_prepare, -1);
4385
+ rb_define_method(rb_cPGconn, "exec_prepared", pgconn_async_exec_prepared, -1);
4386
+ rb_define_method(rb_cPGconn, "describe_prepared", pgconn_async_describe_prepared, 1);
4387
+ rb_define_method(rb_cPGconn, "describe_portal", pgconn_async_describe_portal, 1);
4388
+
4389
+ rb_define_alias(rb_cPGconn, "async_exec", "exec");
4390
+ rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4391
+ rb_define_alias(rb_cPGconn, "async_exec_params", "exec_params");
4392
+ rb_define_alias(rb_cPGconn, "async_prepare", "prepare");
4393
+ rb_define_alias(rb_cPGconn, "async_exec_prepared", "exec_prepared");
4394
+ rb_define_alias(rb_cPGconn, "async_describe_prepared", "describe_prepared");
4395
+ rb_define_alias(rb_cPGconn, "async_describe_portal", "describe_portal");
4396
+
3990
4397
  rb_define_method(rb_cPGconn, "make_empty_pgresult", pgconn_make_empty_pgresult, 1);
3991
4398
  rb_define_method(rb_cPGconn, "escape_string", pgconn_s_escape, 1);
3992
4399
  rb_define_alias(rb_cPGconn, "escape", "escape_string");
3993
- #ifdef HAVE_PQESCAPELITERAL
3994
4400
  rb_define_method(rb_cPGconn, "escape_literal", pgconn_escape_literal, 1);
3995
- #endif
3996
- #ifdef HAVE_PQESCAPEIDENTIFIER
3997
4401
  rb_define_method(rb_cPGconn, "escape_identifier", pgconn_escape_identifier, 1);
3998
- #endif
3999
4402
  rb_define_method(rb_cPGconn, "escape_bytea", pgconn_s_escape_bytea, 1);
4000
4403
  rb_define_method(rb_cPGconn, "unescape_bytea", pgconn_s_unescape_bytea, 1);
4001
- #ifdef HAVE_PQSETSINGLEROWMODE
4002
4404
  rb_define_method(rb_cPGconn, "set_single_row_mode", pgconn_set_single_row_mode, 0);
4003
- #endif
4004
4405
 
4005
4406
  /****** PG::Connection INSTANCE METHODS: Asynchronous Command Processing ******/
4006
4407
  rb_define_method(rb_cPGconn, "send_query", pgconn_send_query, -1);
4408
+ rb_define_method(rb_cPGconn, "send_query_params", pgconn_send_query_params, -1);
4007
4409
  rb_define_method(rb_cPGconn, "send_prepare", pgconn_send_prepare, -1);
4008
4410
  rb_define_method(rb_cPGconn, "send_query_prepared", pgconn_send_query_prepared, -1);
4009
4411
  rb_define_method(rb_cPGconn, "send_describe_prepared", pgconn_send_describe_prepared, 1);
4010
4412
  rb_define_method(rb_cPGconn, "send_describe_portal", pgconn_send_describe_portal, 1);
4011
- rb_define_method(rb_cPGconn, "get_result", pgconn_get_result, 0);
4413
+ rb_define_method(rb_cPGconn, "sync_get_result", pgconn_sync_get_result, 0);
4012
4414
  rb_define_method(rb_cPGconn, "consume_input", pgconn_consume_input, 0);
4013
4415
  rb_define_method(rb_cPGconn, "is_busy", pgconn_is_busy, 0);
4014
- rb_define_method(rb_cPGconn, "setnonblocking", pgconn_setnonblocking, 1);
4015
- rb_define_method(rb_cPGconn, "isnonblocking", pgconn_isnonblocking, 0);
4016
- rb_define_alias(rb_cPGconn, "nonblocking?", "isnonblocking");
4017
- rb_define_method(rb_cPGconn, "flush", pgconn_flush, 0);
4416
+ rb_define_method(rb_cPGconn, "sync_setnonblocking", pgconn_sync_setnonblocking, 1);
4417
+ rb_define_method(rb_cPGconn, "sync_isnonblocking", pgconn_sync_isnonblocking, 0);
4418
+ rb_define_method(rb_cPGconn, "sync_flush", pgconn_sync_flush, 0);
4419
+ rb_define_method(rb_cPGconn, "flush", pgconn_async_flush, 0);
4420
+ rb_define_alias(rb_cPGconn, "async_flush", "flush");
4421
+ rb_define_method(rb_cPGconn, "discard_results", pgconn_discard_results, 0);
4018
4422
 
4019
4423
  /****** PG::Connection INSTANCE METHODS: Cancelling Queries in Progress ******/
4020
- rb_define_method(rb_cPGconn, "cancel", pgconn_cancel, 0);
4424
+ rb_define_method(rb_cPGconn, "sync_cancel", pgconn_sync_cancel, 0);
4021
4425
 
4022
4426
  /****** PG::Connection INSTANCE METHODS: NOTIFY ******/
4023
4427
  rb_define_method(rb_cPGconn, "notifies", pgconn_notifies, 0);
4024
4428
 
4025
4429
  /****** PG::Connection INSTANCE METHODS: COPY ******/
4026
- rb_define_method(rb_cPGconn, "put_copy_data", pgconn_put_copy_data, -1);
4027
- rb_define_method(rb_cPGconn, "put_copy_end", pgconn_put_copy_end, -1);
4028
- rb_define_method(rb_cPGconn, "get_copy_data", pgconn_get_copy_data, -1);
4430
+ rb_define_method(rb_cPGconn, "sync_put_copy_data", pgconn_sync_put_copy_data, -1);
4431
+ rb_define_method(rb_cPGconn, "sync_put_copy_end", pgconn_sync_put_copy_end, -1);
4432
+ rb_define_method(rb_cPGconn, "sync_get_copy_data", pgconn_sync_get_copy_data, -1);
4029
4433
 
4030
4434
  /****** PG::Connection INSTANCE METHODS: Control Functions ******/
4031
4435
  rb_define_method(rb_cPGconn, "set_error_verbosity", pgconn_set_error_verbosity, 1);
4436
+ #ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
4437
+ rb_define_method(rb_cPGconn, "set_error_context_visibility", pgconn_set_error_context_visibility, 1 );
4438
+ #endif
4032
4439
  rb_define_method(rb_cPGconn, "trace", pgconn_trace, 1);
4033
4440
  rb_define_method(rb_cPGconn, "untrace", pgconn_untrace, 0);
4034
4441
 
@@ -4038,16 +4445,21 @@ init_pg_connection()
4038
4445
 
4039
4446
  /****** PG::Connection INSTANCE METHODS: Other ******/
4040
4447
  rb_define_method(rb_cPGconn, "get_client_encoding", pgconn_get_client_encoding, 0);
4041
- rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_set_client_encoding, 1);
4448
+ rb_define_method(rb_cPGconn, "sync_set_client_encoding", pgconn_sync_set_client_encoding, 1);
4449
+ rb_define_method(rb_cPGconn, "set_client_encoding", pgconn_async_set_client_encoding, 1);
4450
+ rb_define_alias(rb_cPGconn, "async_set_client_encoding", "set_client_encoding");
4042
4451
  rb_define_alias(rb_cPGconn, "client_encoding=", "set_client_encoding");
4043
- rb_define_method(rb_cPGconn, "transaction", pgconn_transaction, 0);
4044
4452
  rb_define_method(rb_cPGconn, "block", pgconn_block, -1);
4453
+ rb_define_private_method(rb_cPGconn, "flush_data=", pgconn_flush_data_set, 1);
4045
4454
  rb_define_method(rb_cPGconn, "wait_for_notify", pgconn_wait_for_notify, -1);
4046
4455
  rb_define_alias(rb_cPGconn, "notifies_wait", "wait_for_notify");
4047
4456
  rb_define_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4048
- rb_define_method(rb_cPGconn, "async_exec", pgconn_async_exec, -1);
4049
- rb_define_alias(rb_cPGconn, "async_query", "async_exec");
4050
- rb_define_method(rb_cPGconn, "get_last_result", pgconn_get_last_result, 0);
4457
+ rb_define_method(rb_cPGconn, "sync_get_last_result", pgconn_sync_get_last_result, 0);
4458
+ rb_define_method(rb_cPGconn, "get_last_result", pgconn_async_get_last_result, 0);
4459
+ rb_define_alias(rb_cPGconn, "async_get_last_result", "get_last_result");
4460
+ #ifdef HAVE_PQENCRYPTPASSWORDCONN
4461
+ rb_define_method(rb_cPGconn, "sync_encrypt_password", pgconn_sync_encrypt_password, -1);
4462
+ #endif
4051
4463
 
4052
4464
  #ifdef HAVE_PQSSLATTRIBUTE
4053
4465
  rb_define_method(rb_cPGconn, "ssl_in_use?", pgconn_ssl_in_use, 0);
@@ -4055,6 +4467,14 @@ init_pg_connection()
4055
4467
  rb_define_method(rb_cPGconn, "ssl_attribute_names", pgconn_ssl_attribute_names, 0);
4056
4468
  #endif
4057
4469
 
4470
+ #ifdef HAVE_PQENTERPIPELINEMODE
4471
+ rb_define_method(rb_cPGconn, "pipeline_status", pgconn_pipeline_status, 0);
4472
+ rb_define_method(rb_cPGconn, "enter_pipeline_mode", pgconn_enter_pipeline_mode, 0);
4473
+ rb_define_method(rb_cPGconn, "exit_pipeline_mode", pgconn_exit_pipeline_mode, 0);
4474
+ rb_define_method(rb_cPGconn, "pipeline_sync", pgconn_pipeline_sync, 0);
4475
+ rb_define_method(rb_cPGconn, "send_flush_request", pgconn_send_flush_request, 0);
4476
+ #endif
4477
+
4058
4478
  /****** PG::Connection INSTANCE METHODS: Large Object Support ******/
4059
4479
  rb_define_method(rb_cPGconn, "lo_creat", pgconn_locreat, -1);
4060
4480
  rb_define_alias(rb_cPGconn, "locreat", "lo_creat");
@@ -4083,12 +4503,10 @@ init_pg_connection()
4083
4503
  rb_define_method(rb_cPGconn, "lo_unlink", pgconn_lounlink, 1);
4084
4504
  rb_define_alias(rb_cPGconn, "lounlink", "lo_unlink");
4085
4505
 
4086
- #ifdef M17N_SUPPORTED
4087
4506
  rb_define_method(rb_cPGconn, "internal_encoding", pgconn_internal_encoding, 0);
4088
4507
  rb_define_method(rb_cPGconn, "internal_encoding=", pgconn_internal_encoding_set, 1);
4089
4508
  rb_define_method(rb_cPGconn, "external_encoding", pgconn_external_encoding, 0);
4090
4509
  rb_define_method(rb_cPGconn, "set_default_encoding", pgconn_set_default_encoding, 0);
4091
- #endif /* M17N_SUPPORTED */
4092
4510
 
4093
4511
  rb_define_method(rb_cPGconn, "type_map_for_queries=", pgconn_type_map_for_queries_set, 1);
4094
4512
  rb_define_method(rb_cPGconn, "type_map_for_queries", pgconn_type_map_for_queries_get, 0);
@@ -4098,5 +4516,7 @@ init_pg_connection()
4098
4516
  rb_define_method(rb_cPGconn, "encoder_for_put_copy_data", pgconn_encoder_for_put_copy_data_get, 0);
4099
4517
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data=", pgconn_decoder_for_get_copy_data_set, 1);
4100
4518
  rb_define_method(rb_cPGconn, "decoder_for_get_copy_data", pgconn_decoder_for_get_copy_data_get, 0);
4101
- }
4102
4519
 
4520
+ rb_define_method(rb_cPGconn, "field_name_type=", pgconn_field_name_type_set, 1 );
4521
+ rb_define_method(rb_cPGconn, "field_name_type", pgconn_field_name_type_get, 0 );
4522
+ }