pg 1.3.3 → 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 (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);