pg 1.3.3 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) 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} +302 -115
  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.rb +0 -0
  16. data/ext/errorcodes.txt +2 -1
  17. data/ext/extconf.rb +0 -0
  18. data/ext/pg.c +14 -54
  19. data/ext/pg.h +12 -5
  20. data/ext/pg_binary_decoder.c +80 -1
  21. data/ext/pg_binary_encoder.c +225 -1
  22. data/ext/pg_coder.c +17 -8
  23. data/ext/pg_connection.c +385 -266
  24. data/ext/pg_copy_coder.c +307 -18
  25. data/ext/pg_errors.c +1 -1
  26. data/ext/pg_record_coder.c +12 -9
  27. data/ext/pg_result.c +117 -34
  28. data/ext/pg_text_decoder.c +28 -10
  29. data/ext/pg_text_encoder.c +23 -10
  30. data/ext/pg_tuple.c +36 -39
  31. data/ext/pg_type_map.c +4 -3
  32. data/ext/pg_type_map_all_strings.c +3 -3
  33. data/ext/pg_type_map_by_class.c +6 -4
  34. data/ext/pg_type_map_by_column.c +9 -5
  35. data/ext/pg_type_map_by_mri_type.c +1 -1
  36. data/ext/pg_type_map_by_oid.c +8 -5
  37. data/ext/pg_type_map_in_ruby.c +6 -3
  38. data/lib/pg/basic_type_map_based_on_result.rb +21 -1
  39. data/lib/pg/basic_type_map_for_queries.rb +13 -8
  40. data/lib/pg/basic_type_map_for_results.rb +26 -3
  41. data/lib/pg/basic_type_registry.rb +36 -33
  42. data/lib/pg/binary_decoder/date.rb +9 -0
  43. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  44. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  45. data/lib/pg/coder.rb +15 -13
  46. data/lib/pg/connection.rb +269 -139
  47. data/lib/pg/exceptions.rb +14 -1
  48. data/lib/pg/text_decoder/date.rb +18 -0
  49. data/lib/pg/text_decoder/inet.rb +9 -0
  50. data/lib/pg/text_decoder/json.rb +14 -0
  51. data/lib/pg/text_decoder/numeric.rb +9 -0
  52. data/lib/pg/text_decoder/timestamp.rb +30 -0
  53. data/lib/pg/text_encoder/date.rb +12 -0
  54. data/lib/pg/text_encoder/inet.rb +28 -0
  55. data/lib/pg/text_encoder/json.rb +14 -0
  56. data/lib/pg/text_encoder/numeric.rb +9 -0
  57. data/lib/pg/text_encoder/timestamp.rb +24 -0
  58. data/lib/pg/version.rb +1 -1
  59. data/lib/pg.rb +59 -19
  60. data/misc/openssl-pg-segfault.rb +0 -0
  61. data/pg.gemspec +4 -2
  62. data/rakelib/task_extension.rb +1 -1
  63. data/sample/array_insert.rb +0 -0
  64. data/sample/async_api.rb +3 -7
  65. data/sample/async_copyto.rb +0 -0
  66. data/sample/async_mixed.rb +0 -0
  67. data/sample/check_conn.rb +0 -0
  68. data/sample/copydata.rb +0 -0
  69. data/sample/copyfrom.rb +0 -0
  70. data/sample/copyto.rb +0 -0
  71. data/sample/cursor.rb +0 -0
  72. data/sample/disk_usage_report.rb +0 -0
  73. data/sample/issue-119.rb +0 -0
  74. data/sample/losample.rb +0 -0
  75. data/sample/minimal-testcase.rb +0 -0
  76. data/sample/notify_wait.rb +0 -0
  77. data/sample/pg_statistics.rb +0 -0
  78. data/sample/replication_monitor.rb +0 -0
  79. data/sample/test_binary_values.rb +0 -0
  80. data/sample/wal_shipper.rb +0 -0
  81. data/sample/warehouse_partitions.rb +0 -0
  82. data/translation/.po4a-version +7 -0
  83. data/translation/po/all.pot +910 -0
  84. data/translation/po/ja.po +1047 -0
  85. data/translation/po4a.cfg +12 -0
  86. data.tar.gz.sig +0 -0
  87. metadata +101 -32
  88. metadata.gz.sig +0 -0
  89. data/README.ja.rdoc +0 -13
  90. data/README.rdoc +0 -214
  91. data/lib/pg/binary_decoder.rb +0 -23
  92. data/lib/pg/constants.rb +0 -12
  93. data/lib/pg/text_decoder.rb +0 -46
  94. 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
@@ -475,9 +517,7 @@ pgconn_connect_poll(VALUE self)
475
517
  PostgresPollingStatusType status;
476
518
  status = gvl_PQconnectPoll(pg_get_pgconn(self));
477
519
 
478
- if ( status == PGRES_POLLING_FAILED ) {
479
- pgconn_close_socket_io(self);
480
- }
520
+ pgconn_close_socket_io(self);
481
521
 
482
522
  return INT2FIX((int)status);
483
523
  }
@@ -538,7 +578,7 @@ pgconn_reset_start(VALUE self)
538
578
  {
539
579
  pgconn_close_socket_io( self );
540
580
  if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
541
- rb_raise(rb_eUnableToSend, "reset has failed");
581
+ pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
542
582
  return Qnil;
543
583
  }
544
584
 
@@ -556,9 +596,7 @@ pgconn_reset_poll(VALUE self)
556
596
  PostgresPollingStatusType status;
557
597
  status = gvl_PQresetPoll(pg_get_pgconn(self));
558
598
 
559
- if ( status == PGRES_POLLING_FAILED ) {
560
- pgconn_close_socket_io(self);
561
- }
599
+ pgconn_close_socket_io(self);
562
600
 
563
601
  return INT2FIX((int)status);
564
602
  }
@@ -610,7 +648,18 @@ pgconn_pass(VALUE self)
610
648
  * call-seq:
611
649
  * conn.host()
612
650
  *
613
- * 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 .
614
663
  */
615
664
  static VALUE
616
665
  pgconn_host(VALUE self)
@@ -620,6 +669,26 @@ pgconn_host(VALUE self)
620
669
  return rb_str_new2(host);
621
670
  }
622
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
+
623
692
  /*
624
693
  * call-seq:
625
694
  * conn.port()
@@ -630,7 +699,10 @@ static VALUE
630
699
  pgconn_port(VALUE self)
631
700
  {
632
701
  char* port = PQport(pg_get_pgconn(self));
633
- return INT2NUM(atoi(port));
702
+ if (!port || port[0] == '\0')
703
+ return INT2NUM(DEF_PGPORT);
704
+ else
705
+ return INT2NUM(atoi(port));
634
706
  }
635
707
 
636
708
  /*
@@ -690,6 +762,13 @@ pgconn_conninfo( VALUE self )
690
762
  * PG::Constants::CONNECTION_BAD
691
763
  *
692
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
693
772
  */
694
773
  static VALUE
695
774
  pgconn_status(VALUE self)
@@ -814,7 +893,8 @@ pgconn_socket(VALUE self)
814
893
  pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
815
894
 
816
895
  if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
817
- 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
+
818
898
  return INT2NUM(sd);
819
899
  }
820
900
 
@@ -822,13 +902,15 @@ pgconn_socket(VALUE self)
822
902
  * call-seq:
823
903
  * conn.socket_io() -> IO
824
904
  *
825
- * Fetch a memorized IO object created from the Connection's underlying socket.
826
- * This object can be used for IO.select to wait for events while running
827
- * 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.
828
911
  *
829
- * Using this instead of #socket avoids the problem of the underlying connection
830
- * being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
831
- * 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.
832
914
  */
833
915
  static VALUE
834
916
  pgconn_socket_io(VALUE self)
@@ -840,14 +922,15 @@ pgconn_socket_io(VALUE self)
840
922
  VALUE socket_io = this->socket_io;
841
923
 
842
924
  if ( !RTEST(socket_io) ) {
843
- if( (sd = PQsocket(this->pgconn)) < 0)
844
- 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
+ }
845
928
 
846
929
  #ifdef _WIN32
847
930
  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
- }
931
+ if( ruby_sd == -1 )
932
+ pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
933
+
851
934
  this->ruby_sd = ruby_sd;
852
935
  #else
853
936
  ruby_sd = sd;
@@ -859,7 +942,7 @@ pgconn_socket_io(VALUE self)
859
942
  /* Disable autoclose feature */
860
943
  rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
861
944
 
862
- this->socket_io = socket_io;
945
+ RB_OBJ_WRITE(self, &this->socket_io, socket_io);
863
946
  }
864
947
 
865
948
  return socket_io;
@@ -912,7 +995,7 @@ pgconn_backend_key(VALUE self)
912
995
 
913
996
  cancel = (struct pg_cancel*)PQgetCancel(conn);
914
997
  if(cancel == NULL)
915
- rb_raise(rb_ePGerror,"Invalid connection!");
998
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
916
999
 
917
1000
  if( cancel->be_pid != PQbackendPID(conn) )
918
1001
  rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
@@ -1076,7 +1159,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
1076
1159
  },
1077
1160
  0,
1078
1161
  0,
1079
- RUBY_TYPED_FREE_IMMEDIATELY,
1162
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1080
1163
  };
1081
1164
 
1082
1165
  static char *
@@ -1109,7 +1192,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
1109
1192
  },
1110
1193
  0,
1111
1194
  0,
1112
- RUBY_TYPED_FREE_IMMEDIATELY,
1195
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1113
1196
  };
1114
1197
 
1115
1198
  static int
@@ -1448,8 +1531,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1448
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.
1449
1532
  */
1450
1533
  static VALUE
1451
- pgconn_sync_describe_portal(self, stmt_name)
1452
- VALUE self, stmt_name;
1534
+ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1453
1535
  {
1454
1536
  PGresult *result;
1455
1537
  VALUE rb_pgresult;
@@ -1541,9 +1623,9 @@ pgconn_s_escape(VALUE self, VALUE string)
1541
1623
  if( !singleton ) {
1542
1624
  size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
1543
1625
  RSTRING_PTR(string), RSTRING_LEN(string), &error);
1544
- if(error) {
1545
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(pg_get_pgconn(self)));
1546
- }
1626
+ if(error)
1627
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
1628
+
1547
1629
  } else {
1548
1630
  size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
1549
1631
  }
@@ -1639,7 +1721,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
1639
1721
  {
1640
1722
  t_pg_connection *this = pg_get_connection_safe( self );
1641
1723
  char *escaped = NULL;
1642
- VALUE error;
1643
1724
  VALUE result = Qnil;
1644
1725
  int enc_idx = this->enc_idx;
1645
1726
 
@@ -1650,12 +1731,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
1650
1731
 
1651
1732
  escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1652
1733
  if (escaped == NULL)
1653
- {
1654
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1655
- rb_iv_set(error, "@connection", self);
1656
- rb_exc_raise(error);
1657
- return Qnil;
1658
- }
1734
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1735
+
1659
1736
  result = rb_str_new2(escaped);
1660
1737
  PQfreemem(escaped);
1661
1738
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1678,7 +1755,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1678
1755
  {
1679
1756
  t_pg_connection *this = pg_get_connection_safe( self );
1680
1757
  char *escaped = NULL;
1681
- VALUE error;
1682
1758
  VALUE result = Qnil;
1683
1759
  int enc_idx = this->enc_idx;
1684
1760
 
@@ -1689,12 +1765,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
1689
1765
 
1690
1766
  escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
1691
1767
  if (escaped == NULL)
1692
- {
1693
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
1694
- rb_iv_set(error, "@connection", self);
1695
- rb_exc_raise(error);
1696
- return Qnil;
1697
- }
1768
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
1769
+
1698
1770
  result = rb_str_new2(escaped);
1699
1771
  PQfreemem(escaped);
1700
1772
  PG_ENCODING_SET_NOCHECK(result, enc_idx);
@@ -1742,14 +1814,10 @@ static VALUE
1742
1814
  pgconn_set_single_row_mode(VALUE self)
1743
1815
  {
1744
1816
  PGconn *conn = pg_get_pgconn(self);
1745
- VALUE error;
1746
1817
 
1818
+ rb_check_frozen(self);
1747
1819
  if( PQsetSingleRowMode(conn) == 0 )
1748
- {
1749
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
1750
- rb_iv_set(error, "@connection", self);
1751
- rb_exc_raise(error);
1752
- }
1820
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1753
1821
 
1754
1822
  return self;
1755
1823
  }
@@ -1773,15 +1841,12 @@ static VALUE
1773
1841
  pgconn_send_query(int argc, VALUE *argv, VALUE self)
1774
1842
  {
1775
1843
  t_pg_connection *this = pg_get_connection_safe( self );
1776
- VALUE error;
1777
1844
 
1778
1845
  /* If called with no or nil parameters, use PQexec for compatibility */
1779
1846
  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));
1782
- rb_iv_set(error, "@connection", self);
1783
- rb_exc_raise(error);
1784
- }
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
+
1785
1850
  pgconn_wait_for_flush( self );
1786
1851
  return Qnil;
1787
1852
  }
@@ -1838,7 +1903,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1838
1903
  t_pg_connection *this = pg_get_connection_safe( self );
1839
1904
  int result;
1840
1905
  VALUE command, in_res_fmt;
1841
- VALUE error;
1842
1906
  int nParams;
1843
1907
  int resultFormat;
1844
1908
  struct query_params_data paramsData = { this->enc_idx };
@@ -1855,11 +1919,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
1855
1919
 
1856
1920
  free_query_params( &paramsData );
1857
1921
 
1858
- if(result == 0) {
1859
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1860
- rb_iv_set(error, "@connection", self);
1861
- rb_exc_raise(error);
1862
- }
1922
+ if(result == 0)
1923
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1924
+
1863
1925
  pgconn_wait_for_flush( self );
1864
1926
  return Qnil;
1865
1927
  }
@@ -1891,7 +1953,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1891
1953
  int result;
1892
1954
  VALUE name, command, in_paramtypes;
1893
1955
  VALUE param;
1894
- VALUE error;
1895
1956
  int i = 0;
1896
1957
  int nParams = 0;
1897
1958
  Oid *paramTypes = NULL;
@@ -1920,9 +1981,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
1920
1981
  xfree(paramTypes);
1921
1982
 
1922
1983
  if(result == 0) {
1923
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1924
- rb_iv_set(error, "@connection", self);
1925
- rb_exc_raise(error);
1984
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
1926
1985
  }
1927
1986
  pgconn_wait_for_flush( self );
1928
1987
  return Qnil;
@@ -1966,7 +2025,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1966
2025
  t_pg_connection *this = pg_get_connection_safe( self );
1967
2026
  int result;
1968
2027
  VALUE name, in_res_fmt;
1969
- VALUE error;
1970
2028
  int nParams;
1971
2029
  int resultFormat;
1972
2030
  struct query_params_data paramsData = { this->enc_idx };
@@ -1988,11 +2046,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
1988
2046
 
1989
2047
  free_query_params( &paramsData );
1990
2048
 
1991
- if(result == 0) {
1992
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
1993
- rb_iv_set(error, "@connection", self);
1994
- rb_exc_raise(error);
1995
- }
2049
+ if(result == 0)
2050
+ pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
2051
+
1996
2052
  pgconn_wait_for_flush( self );
1997
2053
  return Qnil;
1998
2054
  }
@@ -2007,14 +2063,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
2007
2063
  static VALUE
2008
2064
  pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2009
2065
  {
2010
- VALUE error;
2011
2066
  t_pg_connection *this = pg_get_connection_safe( self );
2012
2067
  /* returns 0 on failure */
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));
2015
- rb_iv_set(error, "@connection", self);
2016
- rb_exc_raise(error);
2017
- }
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
+
2018
2071
  pgconn_wait_for_flush( self );
2019
2072
  return Qnil;
2020
2073
  }
@@ -2030,14 +2083,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
2030
2083
  static VALUE
2031
2084
  pgconn_send_describe_portal(VALUE self, VALUE portal)
2032
2085
  {
2033
- VALUE error;
2034
2086
  t_pg_connection *this = pg_get_connection_safe( self );
2035
2087
  /* returns 0 on failure */
2036
- if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0) {
2037
- error = rb_exc_new2(rb_eUnableToSend, PQerrorMessage(this->pgconn));
2038
- rb_iv_set(error, "@connection", self);
2039
- rb_exc_raise(error);
2040
- }
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
+
2041
2091
  pgconn_wait_for_flush( self );
2042
2092
  return Qnil;
2043
2093
  }
@@ -2070,18 +2120,15 @@ pgconn_sync_get_result(VALUE self)
2070
2120
  * or *notifies* to see if the state has changed.
2071
2121
  */
2072
2122
  static VALUE
2073
- pgconn_consume_input(self)
2074
- VALUE self;
2123
+ pgconn_consume_input(VALUE self)
2075
2124
  {
2076
- VALUE error;
2077
2125
  PGconn *conn = pg_get_pgconn(self);
2078
2126
  /* returns 0 on error */
2079
2127
  if(PQconsumeInput(conn) == 0) {
2080
2128
  pgconn_close_socket_io(self);
2081
- error = rb_exc_new2(rb_eConnectionBad, PQerrorMessage(conn));
2082
- rb_iv_set(error, "@connection", self);
2083
- rb_exc_raise(error);
2129
+ pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
2084
2130
  }
2131
+
2085
2132
  return Qnil;
2086
2133
  }
2087
2134
 
@@ -2093,19 +2140,17 @@ pgconn_consume_input(self)
2093
2140
  * #get_result would block. Otherwise returns +false+.
2094
2141
  */
2095
2142
  static VALUE
2096
- pgconn_is_busy(self)
2097
- VALUE self;
2143
+ pgconn_is_busy(VALUE self)
2098
2144
  {
2099
2145
  return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2100
2146
  }
2101
2147
 
2102
2148
  static VALUE
2103
- pgconn_sync_setnonblocking(self, state)
2104
- VALUE self, state;
2149
+ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2105
2150
  {
2106
2151
  int arg;
2107
- VALUE error;
2108
2152
  PGconn *conn = pg_get_pgconn(self);
2153
+ rb_check_frozen(self);
2109
2154
  if(state == Qtrue)
2110
2155
  arg = 1;
2111
2156
  else if (state == Qfalse)
@@ -2113,18 +2158,15 @@ pgconn_sync_setnonblocking(self, state)
2113
2158
  else
2114
2159
  rb_raise(rb_eArgError, "Boolean value expected");
2115
2160
 
2116
- if(PQsetnonblocking(conn, arg) == -1) {
2117
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2118
- rb_iv_set(error, "@connection", self);
2119
- rb_exc_raise(error);
2120
- }
2161
+ if(PQsetnonblocking(conn, arg) == -1)
2162
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2163
+
2121
2164
  return Qnil;
2122
2165
  }
2123
2166
 
2124
2167
 
2125
2168
  static VALUE
2126
- pgconn_sync_isnonblocking(self)
2127
- VALUE self;
2169
+ pgconn_sync_isnonblocking(VALUE self)
2128
2170
  {
2129
2171
  return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
2130
2172
  }
@@ -2133,14 +2175,10 @@ static VALUE
2133
2175
  pgconn_sync_flush(VALUE self)
2134
2176
  {
2135
2177
  PGconn *conn = pg_get_pgconn(self);
2136
- int ret;
2137
- VALUE error;
2138
- ret = PQflush(conn);
2139
- if(ret == -1) {
2140
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
2141
- rb_iv_set(error, "@connection", self);
2142
- rb_exc_raise(error);
2143
- }
2178
+ int ret = PQflush(conn);
2179
+ if(ret == -1)
2180
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2181
+
2144
2182
  return (ret) ? Qfalse : Qtrue;
2145
2183
  }
2146
2184
 
@@ -2154,7 +2192,7 @@ pgconn_sync_cancel(VALUE self)
2154
2192
 
2155
2193
  cancel = PQgetCancel(pg_get_pgconn(self));
2156
2194
  if(cancel == NULL)
2157
- rb_raise(rb_ePGerror,"Invalid connection!");
2195
+ pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
2158
2196
 
2159
2197
  ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
2160
2198
  if(ret == 1)
@@ -2343,21 +2381,12 @@ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
2343
2381
  static void *
2344
2382
  wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
2345
2383
  {
2346
- VALUE socket_io;
2347
2384
  VALUE ret;
2348
2385
  void *retval;
2349
2386
  struct timeval aborttime={0,0}, currtime, waittime;
2350
2387
  VALUE wait_timeout = Qnil;
2351
2388
  PGconn *conn = pg_get_pgconn(self);
2352
2389
 
2353
- socket_io = pgconn_socket_io(self);
2354
-
2355
- /* Check for connection errors (PQisBusy is true on connection errors) */
2356
- if ( PQconsumeInput(conn) == 0 ) {
2357
- pgconn_close_socket_io(self);
2358
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2359
- }
2360
-
2361
2390
  if ( ptimeout ) {
2362
2391
  gettimeofday(&currtime, NULL);
2363
2392
  timeradd(&currtime, ptimeout, &aborttime);
@@ -2372,6 +2401,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2372
2401
 
2373
2402
  /* Is the given timeout valid? */
2374
2403
  if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
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);
2375
2412
  /* Wait for the socket to become readable before checking again */
2376
2413
  ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
2377
2414
  } else {
@@ -2386,7 +2423,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2386
2423
  /* Check for connection errors (PQisBusy is true on connection errors) */
2387
2424
  if ( PQconsumeInput(conn) == 0 ){
2388
2425
  pgconn_close_socket_io(self);
2389
- rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
2426
+ pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
2390
2427
  }
2391
2428
  }
2392
2429
 
@@ -2399,8 +2436,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
2399
2436
  *
2400
2437
  * Attempts to flush any queued output data to the server.
2401
2438
  * Returns +true+ if data is successfully flushed, +false+
2402
- * if not (can only return +false+ if connection is
2403
- * nonblocking.
2439
+ * if not. It can only return +false+ if connection is
2440
+ * in nonblocking mode.
2404
2441
  * Raises PG::Error if some other failure occurred.
2405
2442
  */
2406
2443
  static VALUE
@@ -2412,8 +2449,9 @@ pgconn_async_flush(VALUE self)
2412
2449
  VALUE socket_io = pgconn_socket_io(self);
2413
2450
  events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2414
2451
 
2415
- if (events & PG_RUBY_IO_READABLE)
2452
+ if (events & PG_RUBY_IO_READABLE){
2416
2453
  pgconn_consume_input(self);
2454
+ }
2417
2455
  }
2418
2456
  return Qtrue;
2419
2457
  }
@@ -2429,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
2429
2467
  static VALUE
2430
2468
  pgconn_flush_data_set( VALUE self, VALUE enabled ){
2431
2469
  t_pg_connection *conn = pg_get_connection(self);
2470
+ rb_check_frozen(self);
2432
2471
  conn->flush_data = RTEST(enabled);
2433
2472
  return enabled;
2434
2473
  }
@@ -2536,11 +2575,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
2536
2575
  Check_Type(buffer, T_STRING);
2537
2576
 
2538
2577
  ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
2539
- if(ret == -1) {
2540
- VALUE error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2541
- rb_iv_set(error, "@connection", self);
2542
- rb_exc_raise(error);
2543
- }
2578
+ if(ret == -1)
2579
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2580
+
2544
2581
  RB_GC_GUARD(intermediate);
2545
2582
  RB_GC_GUARD(buffer);
2546
2583
 
@@ -2551,7 +2588,6 @@ static VALUE
2551
2588
  pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2552
2589
  {
2553
2590
  VALUE str;
2554
- VALUE error;
2555
2591
  int ret;
2556
2592
  const char *error_message = NULL;
2557
2593
  t_pg_connection *this = pg_get_connection_safe( self );
@@ -2562,11 +2598,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
2562
2598
  error_message = pg_cstr_enc(str, this->enc_idx);
2563
2599
 
2564
2600
  ret = gvl_PQputCopyEnd(this->pgconn, error_message);
2565
- if(ret == -1) {
2566
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2567
- rb_iv_set(error, "@connection", self);
2568
- rb_exc_raise(error);
2569
- }
2601
+ if(ret == -1)
2602
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2603
+
2570
2604
  return (ret) ? Qtrue : Qfalse;
2571
2605
  }
2572
2606
 
@@ -2574,7 +2608,6 @@ static VALUE
2574
2608
  pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2575
2609
  {
2576
2610
  VALUE async_in;
2577
- VALUE error;
2578
2611
  VALUE result;
2579
2612
  int ret;
2580
2613
  char *buffer;
@@ -2594,10 +2627,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
2594
2627
  }
2595
2628
 
2596
2629
  ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
2597
- if(ret == -2) { /* error */
2598
- error = rb_exc_new2(rb_ePGerror, PQerrorMessage(this->pgconn));
2599
- rb_iv_set(error, "@connection", self);
2600
- rb_exc_raise(error);
2630
+ if(ret == -2){ /* error */
2631
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
2601
2632
  }
2602
2633
  if(ret == -1) { /* No data left */
2603
2634
  return Qnil;
@@ -2691,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
2691
2722
  VALUE new_file;
2692
2723
  t_pg_connection *this = pg_get_connection_safe( self );
2693
2724
 
2725
+ rb_check_frozen(self);
2694
2726
  if(!rb_respond_to(stream,rb_intern("fileno")))
2695
2727
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2696
2728
 
@@ -2712,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
2712
2744
  rb_raise(rb_eArgError, "stream is not writable");
2713
2745
 
2714
2746
  new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
2715
- this->trace_stream = new_file;
2747
+ RB_OBJ_WRITE(self, &this->trace_stream, new_file);
2716
2748
 
2717
2749
  PQtrace(this->pgconn, new_fp);
2718
2750
  return Qnil;
@@ -2731,7 +2763,7 @@ pgconn_untrace(VALUE self)
2731
2763
 
2732
2764
  PQuntrace(this->pgconn);
2733
2765
  rb_funcall(this->trace_stream, rb_intern("close"), 0);
2734
- this->trace_stream = Qnil;
2766
+ RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
2735
2767
  return Qnil;
2736
2768
  }
2737
2769
 
@@ -2790,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
2790
2822
  VALUE proc, old_proc;
2791
2823
  t_pg_connection *this = pg_get_connection_safe( self );
2792
2824
 
2825
+ rb_check_frozen(self);
2793
2826
  /* If default_notice_receiver is unset, assume that the current
2794
2827
  * notice receiver is the default, and save it to a global variable.
2795
2828
  * This should not be a problem because the default receiver is
2796
2829
  * always the same, so won't vary among connections.
2797
2830
  */
2798
- if(default_notice_receiver == NULL)
2799
- 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);
2800
2833
 
2801
2834
  old_proc = this->notice_receiver;
2802
2835
  if( rb_block_given_p() ) {
@@ -2805,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
2805
2838
  } else {
2806
2839
  /* if no block is given, set back to default */
2807
2840
  proc = Qnil;
2808
- PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
2841
+ PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
2809
2842
  }
2810
2843
 
2811
- this->notice_receiver = proc;
2844
+ RB_OBJ_WRITE(self, &this->notice_receiver, proc);
2812
2845
  return old_proc;
2813
2846
  }
2814
2847
 
@@ -2823,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
2823
2856
  VALUE self = (VALUE)arg;
2824
2857
  t_pg_connection *this = pg_get_connection( self );
2825
2858
 
2826
- if (this->notice_receiver != Qnil) {
2859
+ if (this->notice_processor != Qnil) {
2827
2860
  VALUE message_str = rb_str_new2(message);
2828
2861
  PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2829
- rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2862
+ rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
2830
2863
  }
2831
2864
  return;
2832
2865
  }
@@ -2850,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
2850
2883
  VALUE proc, old_proc;
2851
2884
  t_pg_connection *this = pg_get_connection_safe( self );
2852
2885
 
2886
+ rb_check_frozen(self);
2853
2887
  /* If default_notice_processor is unset, assume that the current
2854
2888
  * notice processor is the default, and save it to a global variable.
2855
2889
  * This should not be a problem because the default processor is
2856
2890
  * always the same, so won't vary among connections.
2857
2891
  */
2858
- if(default_notice_processor == NULL)
2859
- 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);
2860
2894
 
2861
- old_proc = this->notice_receiver;
2895
+ old_proc = this->notice_processor;
2862
2896
  if( rb_block_given_p() ) {
2863
2897
  proc = rb_block_proc();
2864
2898
  PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
2865
2899
  } else {
2866
2900
  /* if no block is given, set back to default */
2867
2901
  proc = Qnil;
2868
- PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
2902
+ PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
2869
2903
  }
2870
2904
 
2871
- this->notice_receiver = proc;
2905
+ RB_OBJ_WRITE(self, &this->notice_processor, proc);
2872
2906
  return old_proc;
2873
2907
  }
2874
2908
 
@@ -2900,11 +2934,12 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2900
2934
  {
2901
2935
  PGconn *conn = pg_get_pgconn( self );
2902
2936
 
2937
+ rb_check_frozen(self);
2903
2938
  Check_Type(str, T_STRING);
2904
2939
 
2905
- if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 ) {
2906
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
2907
- }
2940
+ if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
2941
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
2942
+
2908
2943
  pgconn_set_internal_encoding_index( self );
2909
2944
 
2910
2945
  return Qnil;
@@ -2984,7 +3019,7 @@ get_result_readable(PGconn *conn)
2984
3019
  * If +true+ is returned, +conn.is_busy+ will return +false+
2985
3020
  * and +conn.get_result+ will not block.
2986
3021
  */
2987
- static VALUE
3022
+ VALUE
2988
3023
  pgconn_block( int argc, VALUE *argv, VALUE self ) {
2989
3024
  struct timeval timeout;
2990
3025
  struct timeval *ptimeout = NULL;
@@ -3068,11 +3103,12 @@ pgconn_async_get_last_result(VALUE self)
3068
3103
  VALUE rb_pgresult = Qnil;
3069
3104
  PGresult *cur, *prev;
3070
3105
 
3071
- cur = prev = NULL;
3106
+ cur = prev = NULL;
3072
3107
  for(;;) {
3073
3108
  int status;
3074
3109
 
3075
- pgconn_block( 0, NULL, self ); /* wait for input (without blocking) before reading the last result */
3110
+ /* wait for input (without blocking) before reading each result */
3111
+ wait_socket_readable(self, NULL, get_result_readable);
3076
3112
 
3077
3113
  cur = gvl_PQgetResult(conn);
3078
3114
  if (cur == NULL)
@@ -3099,8 +3135,14 @@ pgconn_async_get_last_result(VALUE self)
3099
3135
  * conn.discard_results()
3100
3136
  *
3101
3137
  * 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.
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
+ *
3104
3146
  */
3105
3147
  static VALUE
3106
3148
  pgconn_discard_results(VALUE self)
@@ -3108,8 +3150,12 @@ pgconn_discard_results(VALUE self)
3108
3150
  PGconn *conn = pg_get_pgconn(self);
3109
3151
  VALUE socket_io;
3110
3152
 
3111
- if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3112
- return Qnil;
3153
+ switch( PQtransactionStatus(conn) ) {
3154
+ case PQTRANS_IDLE:
3155
+ case PQTRANS_INTRANS:
3156
+ case PQTRANS_INERROR:
3157
+ return Qnil;
3158
+ default:;
3113
3159
  }
3114
3160
 
3115
3161
  socket_io = pgconn_socket_io(self);
@@ -3122,10 +3168,21 @@ pgconn_discard_results(VALUE self)
3122
3168
  * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3123
3169
  */
3124
3170
  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;
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;
3129
3186
  }
3130
3187
  }
3131
3188
 
@@ -3135,7 +3192,9 @@ pgconn_discard_results(VALUE self)
3135
3192
  status = PQresultStatus(cur);
3136
3193
  PQclear(cur);
3137
3194
  if (status == PGRES_COPY_IN){
3138
- 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
+ }
3139
3198
  }
3140
3199
  if (status == PGRES_COPY_OUT){
3141
3200
  for(;;) {
@@ -3144,10 +3203,7 @@ pgconn_discard_results(VALUE self)
3144
3203
  if( st == 0 ) {
3145
3204
  /* would block -> wait for readable data */
3146
3205
  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
- }
3206
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3151
3207
  } else if( st > 0 ) {
3152
3208
  /* some data retrieved -> discard it */
3153
3209
  PQfreemem(buffer);
@@ -3160,6 +3216,10 @@ pgconn_discard_results(VALUE self)
3160
3216
  }
3161
3217
 
3162
3218
  return Qtrue;
3219
+
3220
+ error:
3221
+ pgconn_close_socket_io(self);
3222
+ return Qfalse;
3163
3223
  }
3164
3224
 
3165
3225
  /*
@@ -3536,11 +3596,10 @@ pgconn_enter_pipeline_mode(VALUE self)
3536
3596
  {
3537
3597
  PGconn *conn = pg_get_pgconn(self);
3538
3598
  int res = PQenterPipelineMode(conn);
3539
- if( res == 1 ) {
3540
- return Qnil;
3541
- } else {
3542
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3543
- }
3599
+ if( res != 1 )
3600
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3601
+
3602
+ return Qnil;
3544
3603
  }
3545
3604
 
3546
3605
  /*
@@ -3559,11 +3618,10 @@ pgconn_exit_pipeline_mode(VALUE self)
3559
3618
  {
3560
3619
  PGconn *conn = pg_get_pgconn(self);
3561
3620
  int res = PQexitPipelineMode(conn);
3562
- if( res == 1 ) {
3563
- return Qnil;
3564
- } else {
3565
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3566
- }
3621
+ if( res != 1 )
3622
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3623
+
3624
+ return Qnil;
3567
3625
  }
3568
3626
 
3569
3627
 
@@ -3583,11 +3641,10 @@ pgconn_pipeline_sync(VALUE self)
3583
3641
  {
3584
3642
  PGconn *conn = pg_get_pgconn(self);
3585
3643
  int res = PQpipelineSync(conn);
3586
- if( res == 1 ) {
3587
- return Qnil;
3588
- } else {
3589
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3590
- }
3644
+ if( res != 1 )
3645
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3646
+
3647
+ return Qnil;
3591
3648
  }
3592
3649
 
3593
3650
  /*
@@ -3607,11 +3664,10 @@ pgconn_send_flush_request(VALUE self)
3607
3664
  {
3608
3665
  PGconn *conn = pg_get_pgconn(self);
3609
3666
  int res = PQsendFlushRequest(conn);
3610
- if( res == 1 ) {
3611
- return Qnil;
3612
- } else {
3613
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3614
- }
3667
+ if( res != 1 )
3668
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3669
+
3670
+ return Qnil;
3615
3671
  }
3616
3672
 
3617
3673
  #endif
@@ -3620,6 +3676,14 @@ pgconn_send_flush_request(VALUE self)
3620
3676
  * LARGE OBJECT SUPPORT
3621
3677
  **************************************************************************/
3622
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
+
3623
3687
  /*
3624
3688
  * call-seq:
3625
3689
  * conn.lo_creat( [mode] ) -> Integer
@@ -3640,9 +3704,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3640
3704
  else
3641
3705
  mode = NUM2INT(nmode);
3642
3706
 
3643
- lo_oid = lo_creat(conn, mode);
3707
+ BLOCKING_BEGIN(conn)
3708
+ lo_oid = lo_creat(conn, mode);
3709
+ BLOCKING_END(conn)
3710
+
3644
3711
  if (lo_oid == 0)
3645
- rb_raise(rb_ePGerror, "lo_creat failed");
3712
+ pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3646
3713
 
3647
3714
  return UINT2NUM(lo_oid);
3648
3715
  }
@@ -3663,7 +3730,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
3663
3730
 
3664
3731
  ret = lo_create(conn, lo_oid);
3665
3732
  if (ret == InvalidOid)
3666
- rb_raise(rb_ePGerror, "lo_create failed");
3733
+ pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
3667
3734
 
3668
3735
  return UINT2NUM(ret);
3669
3736
  }
@@ -3685,9 +3752,12 @@ pgconn_loimport(VALUE self, VALUE filename)
3685
3752
 
3686
3753
  Check_Type(filename, T_STRING);
3687
3754
 
3688
- lo_oid = lo_import(conn, StringValueCStr(filename));
3755
+ BLOCKING_BEGIN(conn)
3756
+ lo_oid = lo_import(conn, StringValueCStr(filename));
3757
+ BLOCKING_END(conn)
3758
+
3689
3759
  if (lo_oid == 0) {
3690
- rb_raise(rb_ePGerror, "%s", PQerrorMessage(conn));
3760
+ pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3691
3761
  }
3692
3762
  return UINT2NUM(lo_oid);
3693
3763
  }
@@ -3703,12 +3773,17 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3703
3773
  {
3704
3774
  PGconn *conn = pg_get_pgconn(self);
3705
3775
  Oid oid;
3776
+ int ret;
3706
3777
  Check_Type(filename, T_STRING);
3707
3778
 
3708
3779
  oid = NUM2UINT(lo_oid);
3709
3780
 
3710
- if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3711
- 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));
3712
3787
  }
3713
3788
  return Qnil;
3714
3789
  }
@@ -3738,8 +3813,12 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3738
3813
  else
3739
3814
  mode = NUM2INT(nmode);
3740
3815
 
3741
- if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3742
- 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));
3743
3822
  }
3744
3823
  return INT2FIX(fd);
3745
3824
  }
@@ -3761,11 +3840,15 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3761
3840
  Check_Type(buffer, T_STRING);
3762
3841
 
3763
3842
  if( RSTRING_LEN(buffer) < 0) {
3764
- rb_raise(rb_ePGerror, "write buffer zero string");
3843
+ pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3765
3844
  }
3766
- if((n = lo_write(conn, fd, StringValuePtr(buffer),
3767
- RSTRING_LEN(buffer))) < 0) {
3768
- 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));
3769
3852
  }
3770
3853
 
3771
3854
  return INT2FIX(n);
@@ -3788,16 +3871,17 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3788
3871
  VALUE str;
3789
3872
  char *buffer;
3790
3873
 
3791
- buffer = ALLOC_N(char, len);
3792
- if(buffer == NULL)
3793
- rb_raise(rb_eNoMemError, "ALLOC failed!");
3874
+ if (len < 0)
3875
+ pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3794
3876
 
3795
- if (len < 0){
3796
- rb_raise(rb_ePGerror,"nagative length %d given", len);
3797
- }
3877
+ buffer = ALLOC_N(char, len);
3798
3878
 
3799
- if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3800
- rb_raise(rb_ePGerror, "lo_read failed");
3879
+ BLOCKING_BEGIN(conn)
3880
+ ret = lo_read(conn, lo_desc, buffer, len);
3881
+ BLOCKING_END(conn)
3882
+
3883
+ if(ret < 0)
3884
+ pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3801
3885
 
3802
3886
  if(ret == 0) {
3803
3887
  xfree(buffer);
@@ -3826,8 +3910,12 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3826
3910
  int lo_desc = NUM2INT(in_lo_desc);
3827
3911
  int ret;
3828
3912
 
3829
- if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3830
- 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");
3831
3919
  }
3832
3920
 
3833
3921
  return INT2FIX(ret);
@@ -3846,8 +3934,12 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3846
3934
  PGconn *conn = pg_get_pgconn(self);
3847
3935
  int lo_desc = NUM2INT(in_lo_desc);
3848
3936
 
3849
- if((position = lo_tell(conn, lo_desc)) < 0)
3850
- 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");
3851
3943
 
3852
3944
  return INT2FIX(position);
3853
3945
  }
@@ -3864,9 +3956,14 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3864
3956
  PGconn *conn = pg_get_pgconn(self);
3865
3957
  int lo_desc = NUM2INT(in_lo_desc);
3866
3958
  size_t len = NUM2INT(in_len);
3959
+ int ret;
3960
+
3961
+ BLOCKING_BEGIN(conn)
3962
+ ret = lo_truncate(conn,lo_desc,len);
3963
+ BLOCKING_END(conn)
3867
3964
 
3868
- if(lo_truncate(conn,lo_desc,len) < 0)
3869
- rb_raise(rb_ePGerror,"lo_truncate failed");
3965
+ if(ret < 0)
3966
+ pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3870
3967
 
3871
3968
  return Qnil;
3872
3969
  }
@@ -3882,9 +3979,14 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3882
3979
  {
3883
3980
  PGconn *conn = pg_get_pgconn(self);
3884
3981
  int lo_desc = NUM2INT(in_lo_desc);
3982
+ int ret;
3983
+
3984
+ BLOCKING_BEGIN(conn)
3985
+ ret = lo_close(conn,lo_desc);
3986
+ BLOCKING_END(conn)
3885
3987
 
3886
- if(lo_close(conn,lo_desc) < 0)
3887
- rb_raise(rb_ePGerror,"lo_close failed");
3988
+ if(ret < 0)
3989
+ pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3888
3990
 
3889
3991
  return Qnil;
3890
3992
  }
@@ -3900,9 +4002,14 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3900
4002
  {
3901
4003
  PGconn *conn = pg_get_pgconn(self);
3902
4004
  Oid oid = NUM2UINT(in_oid);
4005
+ int ret;
3903
4006
 
3904
- if(lo_unlink(conn,oid) < 0)
3905
- 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");
3906
4013
 
3907
4014
  return Qnil;
3908
4015
  }
@@ -3959,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
3959
4066
  static VALUE
3960
4067
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3961
4068
  {
4069
+ rb_check_frozen(self);
3962
4070
  if (NIL_P(enc)) {
3963
4071
  pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3964
4072
  return enc;
@@ -4013,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4013
4121
  {
4014
4122
  VALUE query_format, query;
4015
4123
 
4124
+ rb_check_frozen(self);
4016
4125
  Check_Type(encname, T_STRING);
4017
4126
  query_format = rb_str_new_cstr("set client_encoding to '%s'");
4018
4127
  query = rb_funcall(query_format, rb_intern("%"), 1, encname);
@@ -4065,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
4065
4174
  rb_encoding *enc;
4066
4175
  const char *encname;
4067
4176
 
4177
+ rb_check_frozen(self);
4068
4178
  if (( enc = rb_default_internal_encoding() )) {
4069
4179
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
4070
4180
  if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
@@ -4094,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
4094
4204
  t_typemap *tm;
4095
4205
  UNUSED(tm);
4096
4206
 
4207
+ rb_check_frozen(self);
4097
4208
  /* Check type of method param */
4098
4209
  TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4099
4210
 
4100
- this->type_map_for_queries = typemap;
4211
+ RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
4101
4212
 
4102
4213
  return typemap;
4103
4214
  }
@@ -4134,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
4134
4245
  t_typemap *tm;
4135
4246
  UNUSED(tm);
4136
4247
 
4248
+ rb_check_frozen(self);
4137
4249
  TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4138
- this->type_map_for_results = typemap;
4250
+ RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
4139
4251
 
4140
4252
  return typemap;
4141
4253
  }
@@ -4173,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
4173
4285
  {
4174
4286
  t_pg_connection *this = pg_get_connection( self );
4175
4287
 
4288
+ rb_check_frozen(self);
4176
4289
  if( encoder != Qnil ){
4177
4290
  t_pg_coder *co;
4178
4291
  UNUSED(co);
4179
4292
  /* Check argument type */
4180
4293
  TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
4181
4294
  }
4182
- this->encoder_for_put_copy_data = encoder;
4295
+ RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
4183
4296
 
4184
4297
  return encoder;
4185
4298
  }
@@ -4221,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4221
4334
  {
4222
4335
  t_pg_connection *this = pg_get_connection( self );
4223
4336
 
4337
+ rb_check_frozen(self);
4224
4338
  if( decoder != Qnil ){
4225
4339
  t_pg_coder *co;
4226
4340
  UNUSED(co);
4227
4341
  /* Check argument type */
4228
4342
  TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
4229
4343
  }
4230
- this->decoder_for_get_copy_data = decoder;
4344
+ RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
4231
4345
 
4232
4346
  return decoder;
4233
4347
  }
@@ -4273,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
4273
4387
  {
4274
4388
  t_pg_connection *this = pg_get_connection( self );
4275
4389
 
4390
+ rb_check_frozen(self);
4276
4391
  this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4277
4392
  if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4278
4393
  else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
@@ -4309,7 +4424,7 @@ pgconn_field_name_type_get(VALUE self)
4309
4424
  * Document-class: PG::Connection
4310
4425
  */
4311
4426
  void
4312
- init_pg_connection()
4427
+ init_pg_connection(void)
4313
4428
  {
4314
4429
  s_id_encode = rb_intern("encode");
4315
4430
  s_id_autoclose_set = rb_intern("autoclose=");
@@ -4336,6 +4451,7 @@ init_pg_connection()
4336
4451
  rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
4337
4452
  rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
4338
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);
4339
4455
  rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
4340
4456
  rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
4341
4457
 
@@ -4353,6 +4469,9 @@ init_pg_connection()
4353
4469
  rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
4354
4470
  rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
4355
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
4356
4475
  rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
4357
4476
  rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
4358
4477
  rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);