pg 1.3.4 → 1.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +15 -9
  4. data/.github/workflows/binary-gems.yml +43 -12
  5. data/.github/workflows/source-gem.yml +28 -20
  6. data/.gitignore +11 -2
  7. data/.travis.yml +2 -2
  8. data/{History.rdoc → History.md} +293 -122
  9. data/README.ja.md +276 -0
  10. data/README.md +286 -0
  11. data/Rakefile +15 -6
  12. data/Rakefile.cross +7 -11
  13. data/certs/larskanis-2023.pem +24 -0
  14. data/ext/errorcodes.def +4 -0
  15. data/ext/errorcodes.txt +2 -1
  16. data/ext/pg.c +14 -54
  17. data/ext/pg.h +11 -5
  18. data/ext/pg_binary_decoder.c +80 -1
  19. data/ext/pg_binary_encoder.c +225 -1
  20. data/ext/pg_coder.c +17 -8
  21. data/ext/pg_connection.c +380 -250
  22. data/ext/pg_copy_coder.c +307 -18
  23. data/ext/pg_errors.c +1 -1
  24. data/ext/pg_record_coder.c +12 -9
  25. data/ext/pg_result.c +104 -27
  26. data/ext/pg_text_decoder.c +28 -10
  27. data/ext/pg_text_encoder.c +23 -10
  28. data/ext/pg_tuple.c +35 -32
  29. data/ext/pg_type_map.c +4 -3
  30. data/ext/pg_type_map_all_strings.c +3 -3
  31. data/ext/pg_type_map_by_class.c +6 -4
  32. data/ext/pg_type_map_by_column.c +9 -5
  33. data/ext/pg_type_map_by_mri_type.c +1 -1
  34. data/ext/pg_type_map_by_oid.c +8 -5
  35. data/ext/pg_type_map_in_ruby.c +6 -3
  36. data/lib/pg/basic_type_map_based_on_result.rb +21 -1
  37. data/lib/pg/basic_type_map_for_queries.rb +13 -8
  38. data/lib/pg/basic_type_map_for_results.rb +26 -3
  39. data/lib/pg/basic_type_registry.rb +36 -33
  40. data/lib/pg/binary_decoder/date.rb +9 -0
  41. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  42. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  43. data/lib/pg/coder.rb +15 -13
  44. data/lib/pg/connection.rb +265 -136
  45. data/lib/pg/exceptions.rb +14 -1
  46. data/lib/pg/text_decoder/date.rb +18 -0
  47. data/lib/pg/text_decoder/inet.rb +9 -0
  48. data/lib/pg/text_decoder/json.rb +14 -0
  49. data/lib/pg/text_decoder/numeric.rb +9 -0
  50. data/lib/pg/text_decoder/timestamp.rb +30 -0
  51. data/lib/pg/text_encoder/date.rb +12 -0
  52. data/lib/pg/text_encoder/inet.rb +28 -0
  53. data/lib/pg/text_encoder/json.rb +14 -0
  54. data/lib/pg/text_encoder/numeric.rb +9 -0
  55. data/lib/pg/text_encoder/timestamp.rb +24 -0
  56. data/lib/pg/version.rb +1 -1
  57. data/lib/pg.rb +59 -19
  58. data/pg.gemspec +4 -2
  59. data/rakelib/task_extension.rb +1 -1
  60. data/translation/.po4a-version +7 -0
  61. data/translation/po/all.pot +910 -0
  62. data/translation/po/ja.po +1047 -0
  63. data/translation/po4a.cfg +12 -0
  64. data.tar.gz.sig +0 -0
  65. metadata +101 -32
  66. metadata.gz.sig +0 -0
  67. data/README.ja.rdoc +0 -13
  68. data/README.rdoc +0 -214
  69. data/lib/pg/binary_decoder.rb +0 -23
  70. data/lib/pg/constants.rb +0 -12
  71. data/lib/pg/text_decoder.rb +0 -46
  72. data/lib/pg/text_encoder.rb +0 -59
data/ext/pg_connection.c CHANGED
@@ -16,19 +16,37 @@ static ID s_id_autoclose_set;
16
16
  static VALUE sym_type, sym_format, sym_value;
17
17
  static VALUE sym_symbol, sym_string, sym_static_symbol;
18
18
 
19
- static PQnoticeReceiver default_notice_receiver = NULL;
20
- static PQnoticeProcessor default_notice_processor = NULL;
21
-
22
19
  static VALUE pgconn_finish( VALUE );
23
20
  static VALUE pgconn_set_default_encoding( VALUE self );
24
21
  static VALUE pgconn_wait_for_flush( VALUE self );
25
22
  static void pgconn_set_internal_encoding_index( VALUE );
26
23
  static const rb_data_type_t pg_connection_type;
24
+ static VALUE pgconn_async_flush(VALUE self);
27
25
 
28
26
  /*
29
27
  * Global functions
30
28
  */
31
29
 
30
+ /*
31
+ * Convenience function to raise connection errors
32
+ */
33
+ #ifdef __GNUC__
34
+ __attribute__((format(printf, 3, 4)))
35
+ #endif
36
+ static void
37
+ pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
38
+ {
39
+ VALUE msg, error;
40
+ va_list ap;
41
+
42
+ va_start(ap, format);
43
+ msg = rb_vsprintf(format, ap);
44
+ va_end(ap);
45
+ error = rb_exc_new_str(klass, msg);
46
+ rb_iv_set(error, "@connection", self);
47
+ rb_exc_raise(error);
48
+ }
49
+
32
50
  /*
33
51
  * Fetch the PG::Connection object data pointer.
34
52
  */
@@ -52,7 +70,7 @@ pg_get_connection_safe( VALUE self )
52
70
  TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
53
71
 
54
72
  if ( !this->pgconn )
55
- rb_raise( rb_eConnectionBad, "connection is closed" );
73
+ pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
56
74
 
57
75
  return this;
58
76
  }
@@ -70,8 +88,9 @@ pg_get_pgconn( VALUE self )
70
88
  t_pg_connection *this;
71
89
  TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
72
90
 
73
- if ( !this->pgconn )
74
- rb_raise( rb_eConnectionBad, "connection is closed" );
91
+ if ( !this->pgconn ){
92
+ pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
93
+ }
75
94
 
76
95
  return this->pgconn;
77
96
  }
@@ -89,14 +108,13 @@ pgconn_close_socket_io( VALUE self )
89
108
 
90
109
  if ( RTEST(socket_io) ) {
91
110
  #if defined(_WIN32)
92
- if( rb_w32_unwrap_io_handle(this->ruby_sd) ){
93
- rb_raise(rb_eConnectionBad, "Could not unwrap win32 socket handle");
94
- }
111
+ if( rb_w32_unwrap_io_handle(this->ruby_sd) )
112
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
95
113
  #endif
96
114
  rb_funcall( socket_io, rb_intern("close"), 0 );
97
115
  }
98
116
 
99
- this->socket_io = Qnil;
117
+ RB_OBJ_WRITE(self, &this->socket_io, Qnil);
100
118
  }
101
119
 
102
120
 
@@ -216,7 +234,7 @@ static const rb_data_type_t pg_connection_type = {
216
234
  },
217
235
  0,
218
236
  0,
219
- 0,
237
+ RUBY_TYPED_WB_PROTECTED,
220
238
  };
221
239
 
222
240
 
@@ -237,14 +255,15 @@ pgconn_s_allocate( VALUE klass )
237
255
  VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
238
256
 
239
257
  this->pgconn = NULL;
240
- this->socket_io = Qnil;
241
- this->notice_receiver = Qnil;
242
- this->notice_processor = Qnil;
243
- this->type_map_for_queries = pg_typemap_all_strings;
244
- this->type_map_for_results = pg_typemap_all_strings;
245
- this->encoder_for_put_copy_data = Qnil;
246
- this->decoder_for_get_copy_data = Qnil;
247
- this->trace_stream = Qnil;
258
+ RB_OBJ_WRITE(self, &this->socket_io, Qnil);
259
+ RB_OBJ_WRITE(self, &this->notice_receiver, Qnil);
260
+ RB_OBJ_WRITE(self, &this->notice_processor, Qnil);
261
+ RB_OBJ_WRITE(self, &this->type_map_for_queries, pg_typemap_all_strings);
262
+ RB_OBJ_WRITE(self, &this->type_map_for_results, pg_typemap_all_strings);
263
+ RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, Qnil);
264
+ RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, Qnil);
265
+ RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
266
+ rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
248
267
 
249
268
  return self;
250
269
  }
@@ -254,7 +273,6 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
254
273
  {
255
274
  t_pg_connection *this;
256
275
  VALUE conninfo;
257
- VALUE error;
258
276
  VALUE self = pgconn_s_allocate( klass );
259
277
 
260
278
  this = pg_get_connection( self );
@@ -262,13 +280,10 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
262
280
  this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
263
281
 
264
282
  if(this->pgconn == NULL)
265
- rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
283
+ rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
266
284
 
267
- if (PQstatus(this->pgconn) == CONNECTION_BAD) {
268
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
269
- rb_iv_set(error, "@connection", self);
270
- rb_exc_raise(error);
271
- }
285
+ if (PQstatus(this->pgconn) == CONNECTION_BAD)
286
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
272
287
 
273
288
  pgconn_set_default_encoding( self );
274
289
 
@@ -301,7 +316,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
301
316
  {
302
317
  VALUE rb_conn;
303
318
  VALUE conninfo;
304
- VALUE error;
305
319
  t_pg_connection *this;
306
320
 
307
321
  /*
@@ -314,13 +328,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
314
328
  this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
315
329
 
316
330
  if( this->pgconn == NULL )
317
- rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
331
+ rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
318
332
 
319
- if ( PQstatus(this->pgconn) == CONNECTION_BAD ) {
320
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(this->pgconn));
321
- rb_iv_set(error, "@connection", rb_conn);
322
- rb_exc_raise(error);
323
- }
333
+ if ( PQstatus(this->pgconn) == CONNECTION_BAD )
334
+ pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
324
335
 
325
336
  if ( rb_block_given_p() ) {
326
337
  return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
@@ -376,6 +387,36 @@ pgconn_s_conndefaults(VALUE self)
376
387
  return array;
377
388
  }
378
389
 
390
+ /*
391
+ * Document-method: PG::Connection.conninfo_parse
392
+ *
393
+ * call-seq:
394
+ * PG::Connection.conninfo_parse(conninfo_string) -> Array
395
+ *
396
+ * Returns parsed connection options from the provided connection string as an array of hashes.
397
+ * Each hash has the same keys as PG::Connection.conndefaults() .
398
+ * The values from the +conninfo_string+ are stored in the +:val+ key.
399
+ */
400
+ static VALUE
401
+ pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
402
+ {
403
+ VALUE array;
404
+ char *errmsg = NULL;
405
+ PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
406
+ if(errmsg){
407
+ VALUE error = rb_str_new_cstr(errmsg);
408
+ PQfreemem(errmsg);
409
+ rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
410
+ }
411
+ array = pgconn_make_conninfo_array( options );
412
+
413
+ PQconninfoFree(options);
414
+
415
+ UNUSED( self );
416
+
417
+ return array;
418
+ }
419
+
379
420
 
380
421
  #ifdef HAVE_PQENCRYPTPASSWORDCONN
381
422
  static VALUE
@@ -396,7 +437,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
396
437
  rval = rb_str_new2( encrypted );
397
438
  PQfreemem( encrypted );
398
439
  } else {
399
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
440
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
400
441
  }
401
442
 
402
443
  return rval;
@@ -450,17 +491,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
450
491
  * the asynchronous connection is ready
451
492
  *
452
493
  * Example:
453
- * conn = PG::Connection.connect_start("dbname=mydatabase")
454
- * socket = conn.socket_io
494
+ * require "io/wait"
495
+ *
496
+ * conn = PG::Connection.connect_start(dbname: 'mydatabase')
455
497
  * status = conn.connect_poll
456
498
  * while(status != PG::PGRES_POLLING_OK) do
457
499
  * # do some work while waiting for the connection to complete
458
500
  * if(status == PG::PGRES_POLLING_READING)
459
- * if(not select([socket], [], [], 10.0))
501
+ * unless conn.socket_io.wait_readable(10.0)
460
502
  * raise "Asynchronous connection timed out!"
461
503
  * end
462
504
  * elsif(status == PG::PGRES_POLLING_WRITING)
463
- * if(not select([], [socket], [], 10.0))
505
+ * unless conn.socket_io.wait_writable(10.0)
464
506
  * raise "Asynchronous connection timed out!"
465
507
  * end
466
508
  * end
@@ -536,7 +578,7 @@ pgconn_reset_start(VALUE self)
536
578
  {
537
579
  pgconn_close_socket_io( self );
538
580
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
539
- rb_raise(rb_eUnableToSend, "reset has failed");
581
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
540
582
  return Qnil;
541
583
  }
542
584
 
@@ -606,7 +648,18 @@ pgconn_pass(VALUE self)
606
648
  * call-seq:
607
649
  * conn.host()
608
650
  *
609
- * Returns the connected server name.
651
+ * Returns the server host name of the active connection.
652
+ * This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
653
+ * (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
654
+ *
655
+ * If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
656
+ * If only hostaddr was specified, then that is returned.
657
+ * If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
658
+ *
659
+ * If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
660
+ *
661
+ * If multiple hosts were specified in the connection parameters, it is not possible to rely on the result of +host+ until the connection is established.
662
+ * The status of the connection can be checked using the function Connection#status .
610
663
  */
611
664
  static VALUE
612
665
  pgconn_host(VALUE self)
@@ -616,6 +669,26 @@ pgconn_host(VALUE self)
616
669
  return rb_str_new2(host);
617
670
  }
618
671
 
672
+ /* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
673
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
674
+ /*
675
+ * call-seq:
676
+ * conn.hostaddr()
677
+ *
678
+ * Returns the server IP address of the active connection.
679
+ * This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
680
+ * If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
681
+ *
682
+ */
683
+ static VALUE
684
+ pgconn_hostaddr(VALUE self)
685
+ {
686
+ char *host = PQhostaddr(pg_get_pgconn(self));
687
+ if (!host) return Qnil;
688
+ return rb_str_new2(host);
689
+ }
690
+ #endif
691
+
619
692
  /*
620
693
  * call-seq:
621
694
  * conn.port()
@@ -626,7 +699,10 @@ static VALUE
626
699
  pgconn_port(VALUE self)
627
700
  {
628
701
  char* port = PQport(pg_get_pgconn(self));
629
- return INT2NUM(atoi(port));
702
+ if (!port || port[0] == '\0')
703
+ return INT2NUM(DEF_PGPORT);
704
+ else
705
+ return INT2NUM(atoi(port));
630
706
  }
631
707
 
632
708
  /*
@@ -686,6 +762,13 @@ pgconn_conninfo( VALUE self )
686
762
  * PG::Constants::CONNECTION_BAD
687
763
  *
688
764
  * ... and other constants of kind PG::Constants::CONNECTION_*
765
+ *
766
+ * This method returns the status of the last command from memory.
767
+ * It doesn't do any socket access hence is not suitable to test the connectivity.
768
+ * See check_socket for a way to verify the socket state.
769
+ *
770
+ * Example:
771
+ * PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
689
772
  */
690
773
  static VALUE
691
774
  pgconn_status(VALUE self)
@@ -810,7 +893,8 @@ pgconn_socket(VALUE self)
810
893
  pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
811
894
 
812
895
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
813
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
896
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
897
+
814
898
  return INT2NUM(sd);
815
899
  }
816
900
 
@@ -818,13 +902,15 @@ pgconn_socket(VALUE self)
818
902
  * call-seq:
819
903
  * conn.socket_io() -> IO
820
904
  *
821
- * Fetch a memorized IO object created from the Connection's underlying socket.
822
- * This object can be used for IO.select to wait for events while running
823
- * asynchronous API calls.
905
+ * Fetch an IO object created from the Connection's underlying socket.
906
+ * This object can be used per <tt>socket_io.wait_readable</tt>, <tt>socket_io.wait_writable</tt> or for <tt>IO.select</tt> to wait for events while running asynchronous API calls.
907
+ * <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
908
+ *
909
+ * The IO object can change while the connection is established, but is memorized afterwards.
910
+ * So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
824
911
  *
825
- * Using this instead of #socket avoids the problem of the underlying connection
826
- * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
827
- * goes out of scope. In contrast to #socket, it also works on Windows.
912
+ * Using this method also works on Windows in contrast to using #socket .
913
+ * It also avoids the problem of the underlying connection being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt> goes out of scope.
828
914
  */
829
915
  static VALUE
830
916
  pgconn_socket_io(VALUE self)
@@ -836,14 +922,15 @@ pgconn_socket_io(VALUE self)
836
922
  VALUE socket_io = this->socket_io;
837
923
 
838
924
  if ( !RTEST(socket_io) ) {
839
- if( (sd = PQsocket(this->pgconn)) < 0)
840
- rb_raise(rb_eConnectionBad, "PQsocket() can't get socket descriptor");
925
+ if( (sd = PQsocket(this->pgconn)) < 0){
926
+ pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
927
+ }
841
928
 
842
929
  #ifdef _WIN32
843
930
  ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
844
- if( ruby_sd == -1 ){
845
- rb_raise(rb_eConnectionBad, "Could not wrap win32 socket handle");
846
- }
931
+ if( ruby_sd == -1 )
932
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
933
+
847
934
  this->ruby_sd = ruby_sd;
848
935
  #else
849
936
  ruby_sd = sd;
@@ -855,7 +942,7 @@ pgconn_socket_io(VALUE self)
855
942
  /* Disable autoclose feature */
856
943
  rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
857
944
 
858
- this->socket_io = socket_io;
945
+ RB_OBJ_WRITE(self, &this->socket_io, socket_io);
859
946
  }
860
947
 
861
948
  return socket_io;
@@ -908,7 +995,7 @@ pgconn_backend_key(VALUE self)
908
995
 
909
996
  cancel = (struct pg_cancel*)PQgetCancel(conn);
910
997
  if(cancel == NULL)
911
- rb_raise(rb_ePGerror,"Invalid connection!");
998
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
912
999
 
913
1000
  if( cancel->be_pid != PQbackendPID(conn) )
914
1001
  rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
@@ -1072,7 +1159,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
1072
1159
  },
1073
1160
  0,
1074
1161
  0,
1075
- RUBY_TYPED_FREE_IMMEDIATELY,
1162
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1076
1163
  };
1077
1164
 
1078
1165
  static char *
@@ -1105,7 +1192,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
1105
1192
  },
1106
1193
  0,
1107
1194
  0,
1108
- RUBY_TYPED_FREE_IMMEDIATELY,
1195
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1109
1196
  };
1110
1197
 
1111
1198
  static int
@@ -1444,8 +1531,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1444
1531
  * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1445
1532
  */
1446
1533
  static VALUE
1447
- pgconn_sync_describe_portal(self, stmt_name)
1448
- VALUE self, stmt_name;
1534
+ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1449
1535
  {
1450
1536
  PGresult *result;
1451
1537
  VALUE rb_pgresult;
@@ -1537,9 +1623,9 @@ pgconn_s_escape(VALUE self, VALUE string)
1537
1623
  if( !singleton ) {
1538
1624
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1539
1625
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1540
- if(error) {
1541
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1542
- }
1626
+ if(error)
1627
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1628
+
1543
1629
  } else {
1544
1630
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1545
1631
  }
@@ -1635,7 +1721,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
1635
1721
  {
1636
1722
  t_pg_connection *this = pg_get_connection_safe( self );
1637
1723
  char *escaped = NULL;
1638
- VALUE error;
1639
1724
  VALUE result = Qnil;
1640
1725
  int enc_idx = this->enc_idx;
1641
1726
 
@@ -1646,12 +1731,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
1646
1731
 
1647
1732
  escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1648
1733
  if (escaped == NULL)
1649
- {
1650
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1651
- rb_iv_set(error, "@connection", self);
1652
- rb_exc_raise(error);
1653
- return Qnil;
1654
- }
1734
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1735
+
1655
1736
  result = rb_str_new2(escaped);
1656
1737
  PQfreemem(escaped);
1657
1738
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1674,7 +1755,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1674
1755
  {
1675
1756
  t_pg_connection *this = pg_get_connection_safe( self );
1676
1757
  char *escaped = NULL;
1677
- VALUE error;
1678
1758
  VALUE result = Qnil;
1679
1759
  int enc_idx = this->enc_idx;
1680
1760
 
@@ -1685,12 +1765,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1685
1765
 
1686
1766
  escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1687
1767
  if (escaped == NULL)
1688
- {
1689
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1690
- rb_iv_set(error, "@connection", self);
1691
- rb_exc_raise(error);
1692
- return Qnil;
1693
- }
1768
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1769
+
1694
1770
  result = rb_str_new2(escaped);
1695
1771
  PQfreemem(escaped);
1696
1772
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1738,14 +1814,10 @@ static VALUE
1738
1814
  pgconn_set_single_row_mode(VALUE self)
1739
1815
  {
1740
1816
  PGconn *conn = pg_get_pgconn(self);
1741
- VALUE error;
1742
1817
 
1818
+ rb_check_frozen(self);
1743
1819
  if( PQsetSingleRowMode(conn) == 0 )
1744
- {
1745
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1746
- rb_iv_set(error, "@connection", self);
1747
- rb_exc_raise(error);
1748
- }
1820
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1749
1821
 
1750
1822
  return self;
1751
1823
  }
@@ -1769,15 +1841,12 @@ static VALUE
1769
1841
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1770
1842
  {
1771
1843
  t_pg_connection *this = pg_get_connection_safe( self );
1772
- VALUE error;
1773
1844
 
1774
1845
  /* If called with no or nil parameters, use PQexec for compatibility */
1775
1846
  if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
1776
- if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0) {
1777
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1778
- rb_iv_set(error, "@connection", self);
1779
- rb_exc_raise(error);
1780
- }
1847
+ if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
1848
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1849
+
1781
1850
  pgconn_wait_for_flush( self );
1782
1851
  return Qnil;
1783
1852
  }
@@ -1834,7 +1903,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1834
1903
  t_pg_connection *this = pg_get_connection_safe( self );
1835
1904
  int result;
1836
1905
  VALUE command, in_res_fmt;
1837
- VALUE error;
1838
1906
  int nParams;
1839
1907
  int resultFormat;
1840
1908
  struct query_params_data paramsData = { this->enc_idx };
@@ -1851,11 +1919,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1851
1919
 
1852
1920
  free_query_params( &paramsData );
1853
1921
 
1854
- if(result == 0) {
1855
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1856
- rb_iv_set(error, "@connection", self);
1857
- rb_exc_raise(error);
1858
- }
1922
+ if(result == 0)
1923
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1924
+
1859
1925
  pgconn_wait_for_flush( self );
1860
1926
  return Qnil;
1861
1927
  }
@@ -1887,7 +1953,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1887
1953
  int result;
1888
1954
  VALUE name, command, in_paramtypes;
1889
1955
  VALUE param;
1890
- VALUE error;
1891
1956
  int i = 0;
1892
1957
  int nParams = 0;
1893
1958
  Oid *paramTypes = NULL;
@@ -1916,9 +1981,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1916
1981
  xfree(paramTypes);
1917
1982
 
1918
1983
  if(result == 0) {
1919
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1920
- rb_iv_set(error, "@connection", self);
1921
- rb_exc_raise(error);
1984
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1922
1985
  }
1923
1986
  pgconn_wait_for_flush( self );
1924
1987
  return Qnil;
@@ -1962,7 +2025,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1962
2025
  t_pg_connection *this = pg_get_connection_safe( self );
1963
2026
  int result;
1964
2027
  VALUE name, in_res_fmt;
1965
- VALUE error;
1966
2028
  int nParams;
1967
2029
  int resultFormat;
1968
2030
  struct query_params_data paramsData = { this->enc_idx };
@@ -1984,11 +2046,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1984
2046
 
1985
2047
  free_query_params( &paramsData );
1986
2048
 
1987
- if(result == 0) {
1988
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1989
- rb_iv_set(error, "@connection", self);
1990
- rb_exc_raise(error);
1991
- }
2049
+ if(result == 0)
2050
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2051
+
1992
2052
  pgconn_wait_for_flush( self );
1993
2053
  return Qnil;
1994
2054
  }
@@ -2003,14 +2063,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2003
2063
  static VALUE
2004
2064
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2005
2065
  {
2006
- VALUE error;
2007
2066
  t_pg_connection *this = pg_get_connection_safe( self );
2008
2067
  /* returns 0 on failure */
2009
- if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0) {
2010
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2011
- rb_iv_set(error, "@connection", self);
2012
- rb_exc_raise(error);
2013
- }
2068
+ if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
2069
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2070
+
2014
2071
  pgconn_wait_for_flush( self );
2015
2072
  return Qnil;
2016
2073
  }
@@ -2026,14 +2083,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2026
2083
  static VALUE
2027
2084
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2028
2085
  {
2029
- VALUE error;
2030
2086
  t_pg_connection *this = pg_get_connection_safe( self );
2031
2087
  /* returns 0 on failure */
2032
- if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2033
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2034
- rb_iv_set(error, "@connection", self);
2035
- rb_exc_raise(error);
2036
- }
2088
+ if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
2089
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2090
+
2037
2091
  pgconn_wait_for_flush( self );
2038
2092
  return Qnil;
2039
2093
  }
@@ -2066,18 +2120,15 @@ pgconn_sync_get_result(VALUE self)
2066
2120
  * or *notifies* to see if the state has changed.
2067
2121
  */
2068
2122
  static VALUE
2069
- pgconn_consume_input(self)
2070
- VALUE self;
2123
+ pgconn_consume_input(VALUE self)
2071
2124
  {
2072
- VALUE error;
2073
2125
  PGconn *conn = pg_get_pgconn(self);
2074
2126
  /* returns 0 on error */
2075
2127
  if(PQconsumeInput(conn) == 0) {
2076
2128
  pgconn_close_socket_io(self);
2077
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2078
- rb_iv_set(error, "@connection", self);
2079
- rb_exc_raise(error);
2129
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2080
2130
  }
2131
+
2081
2132
  return Qnil;
2082
2133
  }
2083
2134
 
@@ -2089,19 +2140,17 @@ pgconn_consume_input(self)
2089
2140
  * #get_result would block. Otherwise returns +false+.
2090
2141
  */
2091
2142
  static VALUE
2092
- pgconn_is_busy(self)
2093
- VALUE self;
2143
+ pgconn_is_busy(VALUE self)
2094
2144
  {
2095
2145
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2096
2146
  }
2097
2147
 
2098
2148
  static VALUE
2099
- pgconn_sync_setnonblocking(self, state)
2100
- VALUE self, state;
2149
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2101
2150
  {
2102
2151
  int arg;
2103
- VALUE error;
2104
2152
  PGconn *conn = pg_get_pgconn(self);
2153
+ rb_check_frozen(self);
2105
2154
  if(state == Qtrue)
2106
2155
  arg = 1;
2107
2156
  else if (state == Qfalse)
@@ -2109,18 +2158,15 @@ pgconn_sync_setnonblocking(self, state)
2109
2158
  else
2110
2159
  rb_raise(rb_eArgError, "Boolean value expected");
2111
2160
 
2112
- if(PQsetnonblocking(conn, arg) == -1) {
2113
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2114
- rb_iv_set(error, "@connection", self);
2115
- rb_exc_raise(error);
2116
- }
2161
+ if(PQsetnonblocking(conn, arg) == -1)
2162
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2163
+
2117
2164
  return Qnil;
2118
2165
  }
2119
2166
 
2120
2167
 
2121
2168
  static VALUE
2122
- pgconn_sync_isnonblocking(self)
2123
- VALUE self;
2169
+ pgconn_sync_isnonblocking(VALUE self)
2124
2170
  {
2125
2171
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2126
2172
  }
@@ -2129,14 +2175,10 @@ static VALUE
2129
2175
  pgconn_sync_flush(VALUE self)
2130
2176
  {
2131
2177
  PGconn *conn = pg_get_pgconn(self);
2132
- int ret;
2133
- VALUE error;
2134
- ret = PQflush(conn);
2135
- if(ret == -1) {
2136
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2137
- rb_iv_set(error, "@connection", self);
2138
- rb_exc_raise(error);
2139
- }
2178
+ int ret = PQflush(conn);
2179
+ if(ret == -1)
2180
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2181
+
2140
2182
  return (ret) ? Qfalse : Qtrue;
2141
2183
  }
2142
2184
 
@@ -2150,7 +2192,7 @@ pgconn_sync_cancel(VALUE self)
2150
2192
 
2151
2193
  cancel = PQgetCancel(pg_get_pgconn(self));
2152
2194
  if(cancel == NULL)
2153
- rb_raise(rb_ePGerror,"Invalid connection!");
2195
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2154
2196
 
2155
2197
  ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2156
2198
  if(ret == 1)
@@ -2359,7 +2401,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2359
2401
 
2360
2402
  /* Is the given timeout valid? */
2361
2403
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
2362
- VALUE socket_io = pgconn_socket_io(self);
2404
+ VALUE socket_io;
2405
+
2406
+ /* before we wait for data, make sure everything has been sent */
2407
+ pgconn_async_flush(self);
2408
+ if ((retval=is_readable(conn)))
2409
+ return retval;
2410
+
2411
+ socket_io = pgconn_socket_io(self);
2363
2412
  /* Wait for the socket to become readable before checking again */
2364
2413
  ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2365
2414
  } else {
@@ -2374,7 +2423,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2374
2423
  /* Check for connection errors (PQisBusy is true on connection errors) */
2375
2424
  if ( PQconsumeInput(conn) == 0 ){
2376
2425
  pgconn_close_socket_io(self);
2377
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2426
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2378
2427
  }
2379
2428
  }
2380
2429
 
@@ -2387,8 +2436,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2387
2436
  *
2388
2437
  * Attempts to flush any queued output data to the server.
2389
2438
  * Returns +true+ if data is successfully flushed, +false+
2390
- * if not (can only return +false+ if connection is
2391
- * nonblocking.
2439
+ * if not. It can only return +false+ if connection is
2440
+ * in nonblocking mode.
2392
2441
  * Raises PG::Error if some other failure occurred.
2393
2442
  */
2394
2443
  static VALUE
@@ -2400,8 +2449,9 @@ pgconn_async_flush(VALUE self)
2400
2449
  VALUE socket_io = pgconn_socket_io(self);
2401
2450
  events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2402
2451
 
2403
- if (events & PG_RUBY_IO_READABLE)
2452
+ if (events & PG_RUBY_IO_READABLE){
2404
2453
  pgconn_consume_input(self);
2454
+ }
2405
2455
  }
2406
2456
  return Qtrue;
2407
2457
  }
@@ -2417,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
2417
2467
  static VALUE
2418
2468
  pgconn_flush_data_set( VALUE self, VALUE enabled ){
2419
2469
  t_pg_connection *conn = pg_get_connection(self);
2470
+ rb_check_frozen(self);
2420
2471
  conn->flush_data = RTEST(enabled);
2421
2472
  return enabled;
2422
2473
  }
@@ -2524,11 +2575,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2524
2575
  Check_Type(buffer, T_STRING);
2525
2576
 
2526
2577
  ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2527
- if(ret == -1) {
2528
- VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2529
- rb_iv_set(error, "@connection", self);
2530
- rb_exc_raise(error);
2531
- }
2578
+ if(ret == -1)
2579
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2580
+
2532
2581
  RB_GC_GUARD(intermediate);
2533
2582
  RB_GC_GUARD(buffer);
2534
2583
 
@@ -2539,7 +2588,6 @@ static VALUE
2539
2588
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2540
2589
  {
2541
2590
  VALUE str;
2542
- VALUE error;
2543
2591
  int ret;
2544
2592
  const char *error_message = NULL;
2545
2593
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2550,11 +2598,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2550
2598
  error_message = pg_cstr_enc(str, this->enc_idx);
2551
2599
 
2552
2600
  ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2553
- if(ret == -1) {
2554
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2555
- rb_iv_set(error, "@connection", self);
2556
- rb_exc_raise(error);
2557
- }
2601
+ if(ret == -1)
2602
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2603
+
2558
2604
  return (ret) ? Qtrue : Qfalse;
2559
2605
  }
2560
2606
 
@@ -2562,7 +2608,6 @@ static VALUE
2562
2608
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2563
2609
  {
2564
2610
  VALUE async_in;
2565
- VALUE error;
2566
2611
  VALUE result;
2567
2612
  int ret;
2568
2613
  char *buffer;
@@ -2582,10 +2627,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2582
2627
  }
2583
2628
 
2584
2629
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2585
- if(ret == -2) { /* error */
2586
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2587
- rb_iv_set(error, "@connection", self);
2588
- rb_exc_raise(error);
2630
+ if(ret == -2){ /* error */
2631
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2589
2632
  }
2590
2633
  if(ret == -1) { /* No data left */
2591
2634
  return Qnil;
@@ -2679,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
2679
2722
  VALUE new_file;
2680
2723
  t_pg_connection *this = pg_get_connection_safe( self );
2681
2724
 
2725
+ rb_check_frozen(self);
2682
2726
  if(!rb_respond_to(stream,rb_intern("fileno")))
2683
2727
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2684
2728
 
@@ -2700,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
2700
2744
  rb_raise(rb_eArgError, "stream is not writable");
2701
2745
 
2702
2746
  new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
2703
- this->trace_stream = new_file;
2747
+ RB_OBJ_WRITE(self, &this->trace_stream, new_file);
2704
2748
 
2705
2749
  PQtrace(this->pgconn, new_fp);
2706
2750
  return Qnil;
@@ -2719,7 +2763,7 @@ pgconn_untrace(VALUE self)
2719
2763
 
2720
2764
  PQuntrace(this->pgconn);
2721
2765
  rb_funcall(this->trace_stream, rb_intern("close"), 0);
2722
- this->trace_stream = Qnil;
2766
+ RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
2723
2767
  return Qnil;
2724
2768
  }
2725
2769
 
@@ -2778,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
2778
2822
  VALUE proc, old_proc;
2779
2823
  t_pg_connection *this = pg_get_connection_safe( self );
2780
2824
 
2825
+ rb_check_frozen(self);
2781
2826
  /* If default_notice_receiver is unset, assume that the current
2782
2827
  * notice receiver is the default, and save it to a global variable.
2783
2828
  * This should not be a problem because the default receiver is
2784
2829
  * always the same, so won't vary among connections.
2785
2830
  */
2786
- if(default_notice_receiver == NULL)
2787
- default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
2831
+ if(this->default_notice_receiver == NULL)
2832
+ this->default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
2788
2833
 
2789
2834
  old_proc = this->notice_receiver;
2790
2835
  if( rb_block_given_p() ) {
@@ -2793,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
2793
2838
  } else {
2794
2839
  /* if no block is given, set back to default */
2795
2840
  proc = Qnil;
2796
- PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
2841
+ PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
2797
2842
  }
2798
2843
 
2799
- this->notice_receiver = proc;
2844
+ RB_OBJ_WRITE(self, &this->notice_receiver, proc);
2800
2845
  return old_proc;
2801
2846
  }
2802
2847
 
@@ -2811,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
2811
2856
  VALUE self = (VALUE)arg;
2812
2857
  t_pg_connection *this = pg_get_connection( self );
2813
2858
 
2814
- if (this->notice_receiver != Qnil) {
2859
+ if (this->notice_processor != Qnil) {
2815
2860
  VALUE message_str = rb_str_new2(message);
2816
2861
  PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2817
- rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2862
+ rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
2818
2863
  }
2819
2864
  return;
2820
2865
  }
@@ -2838,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
2838
2883
  VALUE proc, old_proc;
2839
2884
  t_pg_connection *this = pg_get_connection_safe( self );
2840
2885
 
2886
+ rb_check_frozen(self);
2841
2887
  /* If default_notice_processor is unset, assume that the current
2842
2888
  * notice processor is the default, and save it to a global variable.
2843
2889
  * This should not be a problem because the default processor is
2844
2890
  * always the same, so won't vary among connections.
2845
2891
  */
2846
- if(default_notice_processor == NULL)
2847
- default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
2892
+ if(this->default_notice_processor == NULL)
2893
+ this->default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
2848
2894
 
2849
- old_proc = this->notice_receiver;
2895
+ old_proc = this->notice_processor;
2850
2896
  if( rb_block_given_p() ) {
2851
2897
  proc = rb_block_proc();
2852
2898
  PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
2853
2899
  } else {
2854
2900
  /* if no block is given, set back to default */
2855
2901
  proc = Qnil;
2856
- PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
2902
+ PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
2857
2903
  }
2858
2904
 
2859
- this->notice_receiver = proc;
2905
+ RB_OBJ_WRITE(self, &this->notice_processor, proc);
2860
2906
  return old_proc;
2861
2907
  }
2862
2908
 
@@ -2888,11 +2934,12 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2888
2934
  {
2889
2935
  PGconn *conn = pg_get_pgconn( self );
2890
2936
 
2937
+ rb_check_frozen(self);
2891
2938
  Check_Type(str, T_STRING);
2892
2939
 
2893
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2894
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2895
- }
2940
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2941
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2942
+
2896
2943
  pgconn_set_internal_encoding_index( self );
2897
2944
 
2898
2945
  return Qnil;
@@ -3056,7 +3103,7 @@ pgconn_async_get_last_result(VALUE self)
3056
3103
  VALUE rb_pgresult = Qnil;
3057
3104
  PGresult *cur, *prev;
3058
3105
 
3059
- cur = prev = NULL;
3106
+ cur = prev = NULL;
3060
3107
  for(;;) {
3061
3108
  int status;
3062
3109
 
@@ -3088,8 +3135,14 @@ pgconn_async_get_last_result(VALUE self)
3088
3135
  * conn.discard_results()
3089
3136
  *
3090
3137
  * Silently discard any prior query result that application didn't eat.
3091
- * This is done prior of Connection#exec and sibling methods and can
3092
- * be called explicitly when using the async API.
3138
+ * This is internally used prior to Connection#exec and sibling methods.
3139
+ * It doesn't raise an exception on connection errors, but returns +false+ instead.
3140
+ *
3141
+ * Returns:
3142
+ * * +nil+ when the connection is already idle
3143
+ * * +true+ when some results have been discarded
3144
+ * * +false+ when a failure occured and the connection was closed
3145
+ *
3093
3146
  */
3094
3147
  static VALUE
3095
3148
  pgconn_discard_results(VALUE self)
@@ -3097,8 +3150,12 @@ pgconn_discard_results(VALUE self)
3097
3150
  PGconn *conn = pg_get_pgconn(self);
3098
3151
  VALUE socket_io;
3099
3152
 
3100
- if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3101
- return Qnil;
3153
+ switch( PQtransactionStatus(conn) ) {
3154
+ case PQTRANS_IDLE:
3155
+ case PQTRANS_INTRANS:
3156
+ case PQTRANS_INERROR:
3157
+ return Qnil;
3158
+ default:;
3102
3159
  }
3103
3160
 
3104
3161
  socket_io = pgconn_socket_io(self);
@@ -3111,10 +3168,21 @@ pgconn_discard_results(VALUE self)
3111
3168
  * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3112
3169
  */
3113
3170
  while( gvl_PQisBusy(conn) ){
3114
- pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3115
- if ( PQconsumeInput(conn) == 0 ) {
3116
- pgconn_close_socket_io(self);
3117
- return Qfalse;
3171
+ int events;
3172
+
3173
+ switch( PQflush(conn) ) {
3174
+ case 1:
3175
+ events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
3176
+ if (events & PG_RUBY_IO_READABLE){
3177
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3178
+ }
3179
+ break;
3180
+ case 0:
3181
+ pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3182
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3183
+ break;
3184
+ default:
3185
+ goto error;
3118
3186
  }
3119
3187
  }
3120
3188
 
@@ -3124,7 +3192,9 @@ pgconn_discard_results(VALUE self)
3124
3192
  status = PQresultStatus(cur);
3125
3193
  PQclear(cur);
3126
3194
  if (status == PGRES_COPY_IN){
3127
- gvl_PQputCopyEnd(conn, "COPY terminated by new PQexec");
3195
+ while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
3196
+ pgconn_async_flush(self);
3197
+ }
3128
3198
  }
3129
3199
  if (status == PGRES_COPY_OUT){
3130
3200
  for(;;) {
@@ -3133,10 +3203,7 @@ pgconn_discard_results(VALUE self)
3133
3203
  if( st == 0 ) {
3134
3204
  /* would block -> wait for readable data */
3135
3205
  pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3136
- if ( PQconsumeInput(conn) == 0 ) {
3137
- pgconn_close_socket_io(self);
3138
- return Qfalse;
3139
- }
3206
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3140
3207
  } else if( st > 0 ) {
3141
3208
  /* some data retrieved -> discard it */
3142
3209
  PQfreemem(buffer);
@@ -3149,6 +3216,10 @@ pgconn_discard_results(VALUE self)
3149
3216
  }
3150
3217
 
3151
3218
  return Qtrue;
3219
+
3220
+ error:
3221
+ pgconn_close_socket_io(self);
3222
+ return Qfalse;
3152
3223
  }
3153
3224
 
3154
3225
  /*
@@ -3525,11 +3596,10 @@ pgconn_enter_pipeline_mode(VALUE self)
3525
3596
  {
3526
3597
  PGconn *conn = pg_get_pgconn(self);
3527
3598
  int res = PQenterPipelineMode(conn);
3528
- if( res == 1 ) {
3529
- return Qnil;
3530
- } else {
3531
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3532
- }
3599
+ if( res != 1 )
3600
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3601
+
3602
+ return Qnil;
3533
3603
  }
3534
3604
 
3535
3605
  /*
@@ -3548,11 +3618,10 @@ pgconn_exit_pipeline_mode(VALUE self)
3548
3618
  {
3549
3619
  PGconn *conn = pg_get_pgconn(self);
3550
3620
  int res = PQexitPipelineMode(conn);
3551
- if( res == 1 ) {
3552
- return Qnil;
3553
- } else {
3554
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3555
- }
3621
+ if( res != 1 )
3622
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3623
+
3624
+ return Qnil;
3556
3625
  }
3557
3626
 
3558
3627
 
@@ -3572,11 +3641,10 @@ pgconn_pipeline_sync(VALUE self)
3572
3641
  {
3573
3642
  PGconn *conn = pg_get_pgconn(self);
3574
3643
  int res = PQpipelineSync(conn);
3575
- if( res == 1 ) {
3576
- return Qnil;
3577
- } else {
3578
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3579
- }
3644
+ if( res != 1 )
3645
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3646
+
3647
+ return Qnil;
3580
3648
  }
3581
3649
 
3582
3650
  /*
@@ -3596,11 +3664,10 @@ pgconn_send_flush_request(VALUE self)
3596
3664
  {
3597
3665
  PGconn *conn = pg_get_pgconn(self);
3598
3666
  int res = PQsendFlushRequest(conn);
3599
- if( res == 1 ) {
3600
- return Qnil;
3601
- } else {
3602
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3603
- }
3667
+ if( res != 1 )
3668
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3669
+
3670
+ return Qnil;
3604
3671
  }
3605
3672
 
3606
3673
  #endif
@@ -3609,6 +3676,14 @@ pgconn_send_flush_request(VALUE self)
3609
3676
  * LARGE OBJECT SUPPORT
3610
3677
  **************************************************************************/
3611
3678
 
3679
+ #define BLOCKING_BEGIN(conn) do { \
3680
+ int old_nonblocking = PQisnonblocking(conn); \
3681
+ PQsetnonblocking(conn, 0);
3682
+
3683
+ #define BLOCKING_END(th) \
3684
+ PQsetnonblocking(conn, old_nonblocking); \
3685
+ } while(0);
3686
+
3612
3687
  /*
3613
3688
  * call-seq:
3614
3689
  * conn.lo_creat( [mode] ) -> Integer
@@ -3629,9 +3704,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3629
3704
  else
3630
3705
  mode = NUM2INT(nmode);
3631
3706
 
3632
- lo_oid = lo_creat(conn, mode);
3707
+ BLOCKING_BEGIN(conn)
3708
+ lo_oid = lo_creat(conn, mode);
3709
+ BLOCKING_END(conn)
3710
+
3633
3711
  if (lo_oid == 0)
3634
- rb_raise(rb_ePGerror, "lo_creat failed");
3712
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3635
3713
 
3636
3714
  return UINT2NUM(lo_oid);
3637
3715
  }
@@ -3652,7 +3730,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3652
3730
 
3653
3731
  ret = lo_create(conn, lo_oid);
3654
3732
  if (ret == InvalidOid)
3655
- rb_raise(rb_ePGerror, "lo_create failed");
3733
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3656
3734
 
3657
3735
  return UINT2NUM(ret);
3658
3736
  }
@@ -3674,9 +3752,12 @@ pgconn_loimport(VALUE self, VALUE filename)
3674
3752
 
3675
3753
  Check_Type(filename, T_STRING);
3676
3754
 
3677
- lo_oid = lo_import(conn, StringValueCStr(filename));
3755
+ BLOCKING_BEGIN(conn)
3756
+ lo_oid = lo_import(conn, StringValueCStr(filename));
3757
+ BLOCKING_END(conn)
3758
+
3678
3759
  if (lo_oid == 0) {
3679
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3760
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3680
3761
  }
3681
3762
  return UINT2NUM(lo_oid);
3682
3763
  }
@@ -3692,12 +3773,17 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3692
3773
  {
3693
3774
  PGconn *conn = pg_get_pgconn(self);
3694
3775
  Oid oid;
3776
+ int ret;
3695
3777
  Check_Type(filename, T_STRING);
3696
3778
 
3697
3779
  oid = NUM2UINT(lo_oid);
3698
3780
 
3699
- if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3700
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3781
+ BLOCKING_BEGIN(conn)
3782
+ ret = lo_export(conn, oid, StringValueCStr(filename));
3783
+ BLOCKING_END(conn)
3784
+
3785
+ if (ret < 0) {
3786
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3701
3787
  }
3702
3788
  return Qnil;
3703
3789
  }
@@ -3727,8 +3813,12 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3727
3813
  else
3728
3814
  mode = NUM2INT(nmode);
3729
3815
 
3730
- if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3731
- rb_raise(rb_ePGerror, "can't open large object: %s", PQerrorMessage(conn));
3816
+ BLOCKING_BEGIN(conn)
3817
+ fd = lo_open(conn, lo_oid, mode);
3818
+ BLOCKING_END(conn)
3819
+
3820
+ if(fd < 0) {
3821
+ pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3732
3822
  }
3733
3823
  return INT2FIX(fd);
3734
3824
  }
@@ -3750,11 +3840,15 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3750
3840
  Check_Type(buffer, T_STRING);
3751
3841
 
3752
3842
  if( RSTRING_LEN(buffer) < 0) {
3753
- rb_raise(rb_ePGerror, "write buffer zero string");
3843
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3754
3844
  }
3755
- if((n = lo_write(conn, fd, StringValuePtr(buffer),
3756
- RSTRING_LEN(buffer))) < 0) {
3757
- rb_raise(rb_ePGerror, "lo_write failed: %s", PQerrorMessage(conn));
3845
+ BLOCKING_BEGIN(conn)
3846
+ n = lo_write(conn, fd, StringValuePtr(buffer),
3847
+ RSTRING_LEN(buffer));
3848
+ BLOCKING_END(conn)
3849
+
3850
+ if(n < 0) {
3851
+ pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3758
3852
  }
3759
3853
 
3760
3854
  return INT2FIX(n);
@@ -3777,16 +3871,17 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3777
3871
  VALUE str;
3778
3872
  char *buffer;
3779
3873
 
3780
- buffer = ALLOC_N(char, len);
3781
- if(buffer == NULL)
3782
- rb_raise(rb_eNoMemError, "ALLOC failed!");
3874
+ if (len < 0)
3875
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3783
3876
 
3784
- if (len < 0){
3785
- rb_raise(rb_ePGerror,"nagative length %d given", len);
3786
- }
3877
+ buffer = ALLOC_N(char, len);
3878
+
3879
+ BLOCKING_BEGIN(conn)
3880
+ ret = lo_read(conn, lo_desc, buffer, len);
3881
+ BLOCKING_END(conn)
3787
3882
 
3788
- if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3789
- rb_raise(rb_ePGerror, "lo_read failed");
3883
+ if(ret < 0)
3884
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3790
3885
 
3791
3886
  if(ret == 0) {
3792
3887
  xfree(buffer);
@@ -3815,8 +3910,12 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3815
3910
  int lo_desc = NUM2INT(in_lo_desc);
3816
3911
  int ret;
3817
3912
 
3818
- if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3819
- rb_raise(rb_ePGerror, "lo_lseek failed");
3913
+ BLOCKING_BEGIN(conn)
3914
+ ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
3915
+ BLOCKING_END(conn)
3916
+
3917
+ if(ret < 0) {
3918
+ pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3820
3919
  }
3821
3920
 
3822
3921
  return INT2FIX(ret);
@@ -3835,8 +3934,12 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3835
3934
  PGconn *conn = pg_get_pgconn(self);
3836
3935
  int lo_desc = NUM2INT(in_lo_desc);
3837
3936
 
3838
- if((position = lo_tell(conn, lo_desc)) < 0)
3839
- rb_raise(rb_ePGerror,"lo_tell failed");
3937
+ BLOCKING_BEGIN(conn)
3938
+ position = lo_tell(conn, lo_desc);
3939
+ BLOCKING_END(conn)
3940
+
3941
+ if(position < 0)
3942
+ pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3840
3943
 
3841
3944
  return INT2FIX(position);
3842
3945
  }
@@ -3853,9 +3956,14 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3853
3956
  PGconn *conn = pg_get_pgconn(self);
3854
3957
  int lo_desc = NUM2INT(in_lo_desc);
3855
3958
  size_t len = NUM2INT(in_len);
3959
+ int ret;
3856
3960
 
3857
- if(lo_truncate(conn,lo_desc,len) < 0)
3858
- rb_raise(rb_ePGerror,"lo_truncate failed");
3961
+ BLOCKING_BEGIN(conn)
3962
+ ret = lo_truncate(conn,lo_desc,len);
3963
+ BLOCKING_END(conn)
3964
+
3965
+ if(ret < 0)
3966
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3859
3967
 
3860
3968
  return Qnil;
3861
3969
  }
@@ -3871,9 +3979,14 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3871
3979
  {
3872
3980
  PGconn *conn = pg_get_pgconn(self);
3873
3981
  int lo_desc = NUM2INT(in_lo_desc);
3982
+ int ret;
3874
3983
 
3875
- if(lo_close(conn,lo_desc) < 0)
3876
- rb_raise(rb_ePGerror,"lo_close failed");
3984
+ BLOCKING_BEGIN(conn)
3985
+ ret = lo_close(conn,lo_desc);
3986
+ BLOCKING_END(conn)
3987
+
3988
+ if(ret < 0)
3989
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3877
3990
 
3878
3991
  return Qnil;
3879
3992
  }
@@ -3889,9 +4002,14 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3889
4002
  {
3890
4003
  PGconn *conn = pg_get_pgconn(self);
3891
4004
  Oid oid = NUM2UINT(in_oid);
4005
+ int ret;
3892
4006
 
3893
- if(lo_unlink(conn,oid) < 0)
3894
- rb_raise(rb_ePGerror,"lo_unlink failed");
4007
+ BLOCKING_BEGIN(conn)
4008
+ ret = lo_unlink(conn,oid);
4009
+ BLOCKING_END(conn)
4010
+
4011
+ if(ret < 0)
4012
+ pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3895
4013
 
3896
4014
  return Qnil;
3897
4015
  }
@@ -3948,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
3948
4066
  static VALUE
3949
4067
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3950
4068
  {
4069
+ rb_check_frozen(self);
3951
4070
  if (NIL_P(enc)) {
3952
4071
  pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3953
4072
  return enc;
@@ -4002,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4002
4121
  {
4003
4122
  VALUE query_format, query;
4004
4123
 
4124
+ rb_check_frozen(self);
4005
4125
  Check_Type(encname, T_STRING);
4006
4126
  query_format = rb_str_new_cstr("set client_encoding to '%s'");
4007
4127
  query = rb_funcall(query_format, rb_intern("%"), 1, encname);
@@ -4054,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
4054
4174
  rb_encoding *enc;
4055
4175
  const char *encname;
4056
4176
 
4177
+ rb_check_frozen(self);
4057
4178
  if (( enc = rb_default_internal_encoding() )) {
4058
4179
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
4059
4180
  if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
@@ -4083,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
4083
4204
  t_typemap *tm;
4084
4205
  UNUSED(tm);
4085
4206
 
4207
+ rb_check_frozen(self);
4086
4208
  /* Check type of method param */
4087
4209
  TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4088
4210
 
4089
- this->type_map_for_queries = typemap;
4211
+ RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
4090
4212
 
4091
4213
  return typemap;
4092
4214
  }
@@ -4123,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
4123
4245
  t_typemap *tm;
4124
4246
  UNUSED(tm);
4125
4247
 
4248
+ rb_check_frozen(self);
4126
4249
  TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4127
- this->type_map_for_results = typemap;
4250
+ RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
4128
4251
 
4129
4252
  return typemap;
4130
4253
  }
@@ -4162,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
4162
4285
  {
4163
4286
  t_pg_connection *this = pg_get_connection( self );
4164
4287
 
4288
+ rb_check_frozen(self);
4165
4289
  if( encoder != Qnil ){
4166
4290
  t_pg_coder *co;
4167
4291
  UNUSED(co);
4168
4292
  /* Check argument type */
4169
4293
  TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
4170
4294
  }
4171
- this->encoder_for_put_copy_data = encoder;
4295
+ RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
4172
4296
 
4173
4297
  return encoder;
4174
4298
  }
@@ -4210,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4210
4334
  {
4211
4335
  t_pg_connection *this = pg_get_connection( self );
4212
4336
 
4337
+ rb_check_frozen(self);
4213
4338
  if( decoder != Qnil ){
4214
4339
  t_pg_coder *co;
4215
4340
  UNUSED(co);
4216
4341
  /* Check argument type */
4217
4342
  TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
4218
4343
  }
4219
- this->decoder_for_get_copy_data = decoder;
4344
+ RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
4220
4345
 
4221
4346
  return decoder;
4222
4347
  }
@@ -4262,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
4262
4387
  {
4263
4388
  t_pg_connection *this = pg_get_connection( self );
4264
4389
 
4390
+ rb_check_frozen(self);
4265
4391
  this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4266
4392
  if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4267
4393
  else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
@@ -4298,7 +4424,7 @@ pgconn_field_name_type_get(VALUE self)
4298
4424
  * Document-class: PG::Connection
4299
4425
  */
4300
4426
  void
4301
- init_pg_connection()
4427
+ init_pg_connection(void)
4302
4428
  {
4303
4429
  s_id_encode = rb_intern("encode");
4304
4430
  s_id_autoclose_set = rb_intern("autoclose=");
@@ -4325,6 +4451,7 @@ init_pg_connection()
4325
4451
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4326
4452
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4327
4453
  rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
4454
+ rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
4328
4455
  rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4329
4456
  rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4330
4457
 
@@ -4342,6 +4469,9 @@ init_pg_connection()
4342
4469
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4343
4470
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4344
4471
  rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
4472
+ #if defined(HAVE_PQRESULTMEMORYSIZE)
4473
+ rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
4474
+ #endif
4345
4475
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4346
4476
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4347
4477
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);