pg 1.4.3 → 1.5.3

Sign up to get free protection for your applications and to get access to all the features.
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=");