pg 1.4.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 (72) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +15 -9
  4. data/.github/workflows/binary-gems.yml +43 -12
  5. data/.github/workflows/source-gem.yml +28 -20
  6. data/.gitignore +11 -2
  7. data/.travis.yml +2 -2
  8. data/{History.rdoc → History.md} +251 -145
  9. data/README.ja.md +276 -0
  10. data/README.md +286 -0
  11. data/Rakefile +15 -6
  12. data/Rakefile.cross +7 -11
  13. data/certs/larskanis-2023.pem +24 -0
  14. data/ext/errorcodes.def +4 -0
  15. data/ext/errorcodes.txt +2 -1
  16. data/ext/pg.c +14 -30
  17. data/ext/pg.h +11 -5
  18. data/ext/pg_binary_decoder.c +80 -1
  19. data/ext/pg_binary_encoder.c +225 -1
  20. data/ext/pg_coder.c +17 -8
  21. data/ext/pg_connection.c +162 -64
  22. data/ext/pg_copy_coder.c +307 -18
  23. data/ext/pg_errors.c +1 -1
  24. data/ext/pg_record_coder.c +6 -5
  25. data/ext/pg_result.c +102 -26
  26. data/ext/pg_text_decoder.c +28 -10
  27. data/ext/pg_text_encoder.c +23 -10
  28. data/ext/pg_tuple.c +35 -32
  29. data/ext/pg_type_map.c +4 -3
  30. data/ext/pg_type_map_all_strings.c +3 -3
  31. data/ext/pg_type_map_by_class.c +6 -4
  32. data/ext/pg_type_map_by_column.c +9 -5
  33. data/ext/pg_type_map_by_mri_type.c +1 -1
  34. data/ext/pg_type_map_by_oid.c +8 -5
  35. data/ext/pg_type_map_in_ruby.c +6 -3
  36. data/lib/pg/basic_type_map_based_on_result.rb +21 -1
  37. data/lib/pg/basic_type_map_for_queries.rb +13 -8
  38. data/lib/pg/basic_type_map_for_results.rb +26 -3
  39. data/lib/pg/basic_type_registry.rb +30 -32
  40. data/lib/pg/binary_decoder/date.rb +9 -0
  41. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  42. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  43. data/lib/pg/coder.rb +15 -13
  44. data/lib/pg/connection.rb +148 -86
  45. data/lib/pg/exceptions.rb +7 -0
  46. data/lib/pg/text_decoder/date.rb +18 -0
  47. data/lib/pg/text_decoder/inet.rb +9 -0
  48. data/lib/pg/text_decoder/json.rb +14 -0
  49. data/lib/pg/text_decoder/numeric.rb +9 -0
  50. data/lib/pg/text_decoder/timestamp.rb +30 -0
  51. data/lib/pg/text_encoder/date.rb +12 -0
  52. data/lib/pg/text_encoder/inet.rb +28 -0
  53. data/lib/pg/text_encoder/json.rb +14 -0
  54. data/lib/pg/text_encoder/numeric.rb +9 -0
  55. data/lib/pg/text_encoder/timestamp.rb +24 -0
  56. data/lib/pg/version.rb +1 -1
  57. data/lib/pg.rb +55 -15
  58. data/pg.gemspec +4 -2
  59. data/rakelib/task_extension.rb +1 -1
  60. data/translation/.po4a-version +7 -0
  61. data/translation/po/all.pot +910 -0
  62. data/translation/po/ja.po +1047 -0
  63. data/translation/po4a.cfg +12 -0
  64. data.tar.gz.sig +0 -0
  65. metadata +101 -32
  66. metadata.gz.sig +0 -0
  67. data/README.ja.rdoc +0 -13
  68. data/README.rdoc +0 -214
  69. data/lib/pg/binary_decoder.rb +0 -23
  70. data/lib/pg/constants.rb +0 -12
  71. data/lib/pg/text_decoder.rb +0 -46
  72. data/lib/pg/text_encoder.rb +0 -59
data/ext/pg_connection.c CHANGED
@@ -16,9 +16,6 @@ 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 );
@@ -117,7 +114,7 @@ pgconn_close_socket_io( VALUE self )
117
114
  rb_funcall( socket_io, rb_intern("close"), 0 );
118
115
  }
119
116
 
120
- this->socket_io = Qnil;
117
+ RB_OBJ_WRITE(self, &this->socket_io, Qnil);
121
118
  }
122
119
 
123
120
 
@@ -237,7 +234,7 @@ static const rb_data_type_t pg_connection_type = {
237
234
  },
238
235
  0,
239
236
  0,
240
- 0,
237
+ RUBY_TYPED_WB_PROTECTED,
241
238
  };
242
239
 
243
240
 
@@ -258,14 +255,14 @@ pgconn_s_allocate( VALUE klass )
258
255
  VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
259
256
 
260
257
  this->pgconn = NULL;
261
- this->socket_io = Qnil;
262
- this->notice_receiver = Qnil;
263
- this->notice_processor = Qnil;
264
- this->type_map_for_queries = pg_typemap_all_strings;
265
- this->type_map_for_results = pg_typemap_all_strings;
266
- this->encoder_for_put_copy_data = Qnil;
267
- this->decoder_for_get_copy_data = Qnil;
268
- 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);
269
266
  rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
270
267
 
271
268
  return self;
@@ -702,7 +699,10 @@ static VALUE
702
699
  pgconn_port(VALUE self)
703
700
  {
704
701
  char* port = PQport(pg_get_pgconn(self));
705
- return INT2NUM(atoi(port));
702
+ if (!port || port[0] == '\0')
703
+ return INT2NUM(DEF_PGPORT);
704
+ else
705
+ return INT2NUM(atoi(port));
706
706
  }
707
707
 
708
708
  /*
@@ -763,6 +763,10 @@ pgconn_conninfo( VALUE self )
763
763
  *
764
764
  * ... and other constants of kind PG::Constants::CONNECTION_*
765
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
+ *
766
770
  * Example:
767
771
  * PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
768
772
  */
@@ -938,7 +942,7 @@ pgconn_socket_io(VALUE self)
938
942
  /* Disable autoclose feature */
939
943
  rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
940
944
 
941
- this->socket_io = socket_io;
945
+ RB_OBJ_WRITE(self, &this->socket_io, socket_io);
942
946
  }
943
947
 
944
948
  return socket_io;
@@ -1155,7 +1159,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
1155
1159
  },
1156
1160
  0,
1157
1161
  0,
1158
- RUBY_TYPED_FREE_IMMEDIATELY,
1162
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1159
1163
  };
1160
1164
 
1161
1165
  static char *
@@ -1188,7 +1192,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
1188
1192
  },
1189
1193
  0,
1190
1194
  0,
1191
- RUBY_TYPED_FREE_IMMEDIATELY,
1195
+ RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
1192
1196
  };
1193
1197
 
1194
1198
  static int
@@ -1527,8 +1531,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1527
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.
1528
1532
  */
1529
1533
  static VALUE
1530
- pgconn_sync_describe_portal(self, stmt_name)
1531
- VALUE self, stmt_name;
1534
+ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1532
1535
  {
1533
1536
  PGresult *result;
1534
1537
  VALUE rb_pgresult;
@@ -1812,6 +1815,7 @@ pgconn_set_single_row_mode(VALUE self)
1812
1815
  {
1813
1816
  PGconn *conn = pg_get_pgconn(self);
1814
1817
 
1818
+ rb_check_frozen(self);
1815
1819
  if( PQsetSingleRowMode(conn) == 0 )
1816
1820
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
1817
1821
 
@@ -2146,6 +2150,7 @@ pgconn_sync_setnonblocking(VALUE self, VALUE state)
2146
2150
  {
2147
2151
  int arg;
2148
2152
  PGconn *conn = pg_get_pgconn(self);
2153
+ rb_check_frozen(self);
2149
2154
  if(state == Qtrue)
2150
2155
  arg = 1;
2151
2156
  else if (state == Qfalse)
@@ -2444,8 +2449,9 @@ pgconn_async_flush(VALUE self)
2444
2449
  VALUE socket_io = pgconn_socket_io(self);
2445
2450
  events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
2446
2451
 
2447
- if (events & PG_RUBY_IO_READABLE)
2452
+ if (events & PG_RUBY_IO_READABLE){
2448
2453
  pgconn_consume_input(self);
2454
+ }
2449
2455
  }
2450
2456
  return Qtrue;
2451
2457
  }
@@ -2461,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
2461
2467
  static VALUE
2462
2468
  pgconn_flush_data_set( VALUE self, VALUE enabled ){
2463
2469
  t_pg_connection *conn = pg_get_connection(self);
2470
+ rb_check_frozen(self);
2464
2471
  conn->flush_data = RTEST(enabled);
2465
2472
  return enabled;
2466
2473
  }
@@ -2715,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
2715
2722
  VALUE new_file;
2716
2723
  t_pg_connection *this = pg_get_connection_safe( self );
2717
2724
 
2725
+ rb_check_frozen(self);
2718
2726
  if(!rb_respond_to(stream,rb_intern("fileno")))
2719
2727
  rb_raise(rb_eArgError, "stream does not respond to method: fileno");
2720
2728
 
@@ -2736,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
2736
2744
  rb_raise(rb_eArgError, "stream is not writable");
2737
2745
 
2738
2746
  new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
2739
- this->trace_stream = new_file;
2747
+ RB_OBJ_WRITE(self, &this->trace_stream, new_file);
2740
2748
 
2741
2749
  PQtrace(this->pgconn, new_fp);
2742
2750
  return Qnil;
@@ -2755,7 +2763,7 @@ pgconn_untrace(VALUE self)
2755
2763
 
2756
2764
  PQuntrace(this->pgconn);
2757
2765
  rb_funcall(this->trace_stream, rb_intern("close"), 0);
2758
- this->trace_stream = Qnil;
2766
+ RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
2759
2767
  return Qnil;
2760
2768
  }
2761
2769
 
@@ -2814,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
2814
2822
  VALUE proc, old_proc;
2815
2823
  t_pg_connection *this = pg_get_connection_safe( self );
2816
2824
 
2825
+ rb_check_frozen(self);
2817
2826
  /* If default_notice_receiver is unset, assume that the current
2818
2827
  * notice receiver is the default, and save it to a global variable.
2819
2828
  * This should not be a problem because the default receiver is
2820
2829
  * always the same, so won't vary among connections.
2821
2830
  */
2822
- if(default_notice_receiver == NULL)
2823
- 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);
2824
2833
 
2825
2834
  old_proc = this->notice_receiver;
2826
2835
  if( rb_block_given_p() ) {
@@ -2829,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
2829
2838
  } else {
2830
2839
  /* if no block is given, set back to default */
2831
2840
  proc = Qnil;
2832
- PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
2841
+ PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
2833
2842
  }
2834
2843
 
2835
- this->notice_receiver = proc;
2844
+ RB_OBJ_WRITE(self, &this->notice_receiver, proc);
2836
2845
  return old_proc;
2837
2846
  }
2838
2847
 
@@ -2847,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
2847
2856
  VALUE self = (VALUE)arg;
2848
2857
  t_pg_connection *this = pg_get_connection( self );
2849
2858
 
2850
- if (this->notice_receiver != Qnil) {
2859
+ if (this->notice_processor != Qnil) {
2851
2860
  VALUE message_str = rb_str_new2(message);
2852
2861
  PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
2853
- rb_funcall(this->notice_receiver, rb_intern("call"), 1, message_str);
2862
+ rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
2854
2863
  }
2855
2864
  return;
2856
2865
  }
@@ -2874,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
2874
2883
  VALUE proc, old_proc;
2875
2884
  t_pg_connection *this = pg_get_connection_safe( self );
2876
2885
 
2886
+ rb_check_frozen(self);
2877
2887
  /* If default_notice_processor is unset, assume that the current
2878
2888
  * notice processor is the default, and save it to a global variable.
2879
2889
  * This should not be a problem because the default processor is
2880
2890
  * always the same, so won't vary among connections.
2881
2891
  */
2882
- if(default_notice_processor == NULL)
2883
- 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);
2884
2894
 
2885
- old_proc = this->notice_receiver;
2895
+ old_proc = this->notice_processor;
2886
2896
  if( rb_block_given_p() ) {
2887
2897
  proc = rb_block_proc();
2888
2898
  PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
2889
2899
  } else {
2890
2900
  /* if no block is given, set back to default */
2891
2901
  proc = Qnil;
2892
- PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
2902
+ PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
2893
2903
  }
2894
2904
 
2895
- this->notice_receiver = proc;
2905
+ RB_OBJ_WRITE(self, &this->notice_processor, proc);
2896
2906
  return old_proc;
2897
2907
  }
2898
2908
 
@@ -2924,6 +2934,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
2924
2934
  {
2925
2935
  PGconn *conn = pg_get_pgconn( self );
2926
2936
 
2937
+ rb_check_frozen(self);
2927
2938
  Check_Type(str, T_STRING);
2928
2939
 
2929
2940
  if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
@@ -3092,7 +3103,7 @@ pgconn_async_get_last_result(VALUE self)
3092
3103
  VALUE rb_pgresult = Qnil;
3093
3104
  PGresult *cur, *prev;
3094
3105
 
3095
- cur = prev = NULL;
3106
+ cur = prev = NULL;
3096
3107
  for(;;) {
3097
3108
  int status;
3098
3109
 
@@ -3124,8 +3135,14 @@ pgconn_async_get_last_result(VALUE self)
3124
3135
  * conn.discard_results()
3125
3136
  *
3126
3137
  * Silently discard any prior query result that application didn't eat.
3127
- * This is done prior of Connection#exec and sibling methods and can
3128
- * 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
+ *
3129
3146
  */
3130
3147
  static VALUE
3131
3148
  pgconn_discard_results(VALUE self)
@@ -3133,8 +3150,12 @@ pgconn_discard_results(VALUE self)
3133
3150
  PGconn *conn = pg_get_pgconn(self);
3134
3151
  VALUE socket_io;
3135
3152
 
3136
- if( PQtransactionStatus(conn) == PQTRANS_IDLE ) {
3137
- return Qnil;
3153
+ switch( PQtransactionStatus(conn) ) {
3154
+ case PQTRANS_IDLE:
3155
+ case PQTRANS_INTRANS:
3156
+ case PQTRANS_INERROR:
3157
+ return Qnil;
3158
+ default:;
3138
3159
  }
3139
3160
 
3140
3161
  socket_io = pgconn_socket_io(self);
@@ -3147,10 +3168,21 @@ pgconn_discard_results(VALUE self)
3147
3168
  * To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
3148
3169
  */
3149
3170
  while( gvl_PQisBusy(conn) ){
3150
- pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3151
- if ( PQconsumeInput(conn) == 0 ) {
3152
- pgconn_close_socket_io(self);
3153
- 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;
3154
3186
  }
3155
3187
  }
3156
3188
 
@@ -3160,7 +3192,9 @@ pgconn_discard_results(VALUE self)
3160
3192
  status = PQresultStatus(cur);
3161
3193
  PQclear(cur);
3162
3194
  if (status == PGRES_COPY_IN){
3163
- 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
+ }
3164
3198
  }
3165
3199
  if (status == PGRES_COPY_OUT){
3166
3200
  for(;;) {
@@ -3169,10 +3203,7 @@ pgconn_discard_results(VALUE self)
3169
3203
  if( st == 0 ) {
3170
3204
  /* would block -> wait for readable data */
3171
3205
  pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
3172
- if ( PQconsumeInput(conn) == 0 ) {
3173
- pgconn_close_socket_io(self);
3174
- return Qfalse;
3175
- }
3206
+ if ( PQconsumeInput(conn) == 0 ) goto error;
3176
3207
  } else if( st > 0 ) {
3177
3208
  /* some data retrieved -> discard it */
3178
3209
  PQfreemem(buffer);
@@ -3185,6 +3216,10 @@ pgconn_discard_results(VALUE self)
3185
3216
  }
3186
3217
 
3187
3218
  return Qtrue;
3219
+
3220
+ error:
3221
+ pgconn_close_socket_io(self);
3222
+ return Qfalse;
3188
3223
  }
3189
3224
 
3190
3225
  /*
@@ -3641,6 +3676,14 @@ pgconn_send_flush_request(VALUE self)
3641
3676
  * LARGE OBJECT SUPPORT
3642
3677
  **************************************************************************/
3643
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
+
3644
3687
  /*
3645
3688
  * call-seq:
3646
3689
  * conn.lo_creat( [mode] ) -> Integer
@@ -3661,7 +3704,10 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
3661
3704
  else
3662
3705
  mode = NUM2INT(nmode);
3663
3706
 
3664
- lo_oid = lo_creat(conn, mode);
3707
+ BLOCKING_BEGIN(conn)
3708
+ lo_oid = lo_creat(conn, mode);
3709
+ BLOCKING_END(conn)
3710
+
3665
3711
  if (lo_oid == 0)
3666
3712
  pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
3667
3713
 
@@ -3706,7 +3752,10 @@ pgconn_loimport(VALUE self, VALUE filename)
3706
3752
 
3707
3753
  Check_Type(filename, T_STRING);
3708
3754
 
3709
- lo_oid = lo_import(conn, StringValueCStr(filename));
3755
+ BLOCKING_BEGIN(conn)
3756
+ lo_oid = lo_import(conn, StringValueCStr(filename));
3757
+ BLOCKING_END(conn)
3758
+
3710
3759
  if (lo_oid == 0) {
3711
3760
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3712
3761
  }
@@ -3724,11 +3773,16 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
3724
3773
  {
3725
3774
  PGconn *conn = pg_get_pgconn(self);
3726
3775
  Oid oid;
3776
+ int ret;
3727
3777
  Check_Type(filename, T_STRING);
3728
3778
 
3729
3779
  oid = NUM2UINT(lo_oid);
3730
3780
 
3731
- if (lo_export(conn, oid, StringValueCStr(filename)) < 0) {
3781
+ BLOCKING_BEGIN(conn)
3782
+ ret = lo_export(conn, oid, StringValueCStr(filename));
3783
+ BLOCKING_END(conn)
3784
+
3785
+ if (ret < 0) {
3732
3786
  pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
3733
3787
  }
3734
3788
  return Qnil;
@@ -3759,7 +3813,11 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
3759
3813
  else
3760
3814
  mode = NUM2INT(nmode);
3761
3815
 
3762
- if((fd = lo_open(conn, lo_oid, mode)) < 0) {
3816
+ BLOCKING_BEGIN(conn)
3817
+ fd = lo_open(conn, lo_oid, mode);
3818
+ BLOCKING_END(conn)
3819
+
3820
+ if(fd < 0) {
3763
3821
  pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
3764
3822
  }
3765
3823
  return INT2FIX(fd);
@@ -3784,8 +3842,12 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
3784
3842
  if( RSTRING_LEN(buffer) < 0) {
3785
3843
  pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
3786
3844
  }
3787
- if((n = lo_write(conn, fd, StringValuePtr(buffer),
3788
- RSTRING_LEN(buffer))) < 0) {
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) {
3789
3851
  pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
3790
3852
  }
3791
3853
 
@@ -3813,7 +3875,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
3813
3875
  pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
3814
3876
 
3815
3877
  buffer = ALLOC_N(char, len);
3816
- if((ret = lo_read(conn, lo_desc, buffer, len)) < 0)
3878
+
3879
+ BLOCKING_BEGIN(conn)
3880
+ ret = lo_read(conn, lo_desc, buffer, len);
3881
+ BLOCKING_END(conn)
3882
+
3883
+ if(ret < 0)
3817
3884
  pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
3818
3885
 
3819
3886
  if(ret == 0) {
@@ -3843,7 +3910,11 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
3843
3910
  int lo_desc = NUM2INT(in_lo_desc);
3844
3911
  int ret;
3845
3912
 
3846
- if((ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence))) < 0) {
3913
+ BLOCKING_BEGIN(conn)
3914
+ ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
3915
+ BLOCKING_END(conn)
3916
+
3917
+ if(ret < 0) {
3847
3918
  pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
3848
3919
  }
3849
3920
 
@@ -3863,7 +3934,11 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
3863
3934
  PGconn *conn = pg_get_pgconn(self);
3864
3935
  int lo_desc = NUM2INT(in_lo_desc);
3865
3936
 
3866
- if((position = lo_tell(conn, lo_desc)) < 0)
3937
+ BLOCKING_BEGIN(conn)
3938
+ position = lo_tell(conn, lo_desc);
3939
+ BLOCKING_END(conn)
3940
+
3941
+ if(position < 0)
3867
3942
  pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
3868
3943
 
3869
3944
  return INT2FIX(position);
@@ -3881,8 +3956,13 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
3881
3956
  PGconn *conn = pg_get_pgconn(self);
3882
3957
  int lo_desc = NUM2INT(in_lo_desc);
3883
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)
3884
3964
 
3885
- if(lo_truncate(conn,lo_desc,len) < 0)
3965
+ if(ret < 0)
3886
3966
  pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
3887
3967
 
3888
3968
  return Qnil;
@@ -3899,8 +3979,13 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
3899
3979
  {
3900
3980
  PGconn *conn = pg_get_pgconn(self);
3901
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)
3902
3987
 
3903
- if(lo_close(conn,lo_desc) < 0)
3988
+ if(ret < 0)
3904
3989
  pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
3905
3990
 
3906
3991
  return Qnil;
@@ -3917,8 +4002,13 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
3917
4002
  {
3918
4003
  PGconn *conn = pg_get_pgconn(self);
3919
4004
  Oid oid = NUM2UINT(in_oid);
4005
+ int ret;
4006
+
4007
+ BLOCKING_BEGIN(conn)
4008
+ ret = lo_unlink(conn,oid);
4009
+ BLOCKING_END(conn)
3920
4010
 
3921
- if(lo_unlink(conn,oid) < 0)
4011
+ if(ret < 0)
3922
4012
  pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
3923
4013
 
3924
4014
  return Qnil;
@@ -3976,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
3976
4066
  static VALUE
3977
4067
  pgconn_internal_encoding_set(VALUE self, VALUE enc)
3978
4068
  {
4069
+ rb_check_frozen(self);
3979
4070
  if (NIL_P(enc)) {
3980
4071
  pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
3981
4072
  return enc;
@@ -4030,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
4030
4121
  {
4031
4122
  VALUE query_format, query;
4032
4123
 
4124
+ rb_check_frozen(self);
4033
4125
  Check_Type(encname, T_STRING);
4034
4126
  query_format = rb_str_new_cstr("set client_encoding to '%s'");
4035
4127
  query = rb_funcall(query_format, rb_intern("%"), 1, encname);
@@ -4082,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
4082
4174
  rb_encoding *enc;
4083
4175
  const char *encname;
4084
4176
 
4177
+ rb_check_frozen(self);
4085
4178
  if (( enc = rb_default_internal_encoding() )) {
4086
4179
  encname = pg_get_rb_encoding_as_pg_encoding( enc );
4087
4180
  if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
@@ -4111,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
4111
4204
  t_typemap *tm;
4112
4205
  UNUSED(tm);
4113
4206
 
4207
+ rb_check_frozen(self);
4114
4208
  /* Check type of method param */
4115
4209
  TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4116
4210
 
4117
- this->type_map_for_queries = typemap;
4211
+ RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
4118
4212
 
4119
4213
  return typemap;
4120
4214
  }
@@ -4151,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
4151
4245
  t_typemap *tm;
4152
4246
  UNUSED(tm);
4153
4247
 
4248
+ rb_check_frozen(self);
4154
4249
  TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
4155
- this->type_map_for_results = typemap;
4250
+ RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
4156
4251
 
4157
4252
  return typemap;
4158
4253
  }
@@ -4190,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
4190
4285
  {
4191
4286
  t_pg_connection *this = pg_get_connection( self );
4192
4287
 
4288
+ rb_check_frozen(self);
4193
4289
  if( encoder != Qnil ){
4194
4290
  t_pg_coder *co;
4195
4291
  UNUSED(co);
4196
4292
  /* Check argument type */
4197
4293
  TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
4198
4294
  }
4199
- this->encoder_for_put_copy_data = encoder;
4295
+ RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
4200
4296
 
4201
4297
  return encoder;
4202
4298
  }
@@ -4238,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
4238
4334
  {
4239
4335
  t_pg_connection *this = pg_get_connection( self );
4240
4336
 
4337
+ rb_check_frozen(self);
4241
4338
  if( decoder != Qnil ){
4242
4339
  t_pg_coder *co;
4243
4340
  UNUSED(co);
4244
4341
  /* Check argument type */
4245
4342
  TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
4246
4343
  }
4247
- this->decoder_for_get_copy_data = decoder;
4344
+ RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
4248
4345
 
4249
4346
  return decoder;
4250
4347
  }
@@ -4290,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
4290
4387
  {
4291
4388
  t_pg_connection *this = pg_get_connection( self );
4292
4389
 
4390
+ rb_check_frozen(self);
4293
4391
  this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
4294
4392
  if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
4295
4393
  else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
@@ -4326,7 +4424,7 @@ pgconn_field_name_type_get(VALUE self)
4326
4424
  * Document-class: PG::Connection
4327
4425
  */
4328
4426
  void
4329
- init_pg_connection()
4427
+ init_pg_connection(void)
4330
4428
  {
4331
4429
  s_id_encode = rb_intern("encode");
4332
4430
  s_id_autoclose_set = rb_intern("autoclose=");