pg 1.4.4 → 1.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +15 -9
- data/.github/workflows/binary-gems.yml +42 -11
- data/.github/workflows/source-gem.yml +24 -18
- data/.gitignore +11 -2
- data/.travis.yml +2 -2
- data/{History.rdoc → History.md} +246 -150
- data/README.ja.md +276 -0
- data/README.md +286 -0
- data/Rakefile +13 -4
- data/Rakefile.cross +7 -11
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +4 -0
- data/ext/errorcodes.txt +2 -1
- data/ext/pg.c +13 -28
- data/ext/pg.h +10 -5
- data/ext/pg_binary_decoder.c +79 -0
- data/ext/pg_binary_encoder.c +224 -0
- data/ext/pg_coder.c +16 -7
- data/ext/pg_connection.c +160 -61
- data/ext/pg_copy_coder.c +306 -17
- data/ext/pg_record_coder.c +5 -4
- data/ext/pg_result.c +91 -17
- data/ext/pg_text_decoder.c +28 -10
- data/ext/pg_text_encoder.c +22 -9
- data/ext/pg_tuple.c +34 -31
- data/ext/pg_type_map.c +3 -2
- data/ext/pg_type_map_all_strings.c +2 -2
- data/ext/pg_type_map_by_class.c +5 -3
- data/ext/pg_type_map_by_column.c +7 -3
- data/ext/pg_type_map_by_oid.c +7 -4
- data/ext/pg_type_map_in_ruby.c +5 -2
- data/lib/pg/basic_type_map_based_on_result.rb +21 -1
- data/lib/pg/basic_type_map_for_queries.rb +13 -8
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +30 -32
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +15 -13
- data/lib/pg/connection.rb +104 -30
- data/lib/pg/exceptions.rb +7 -0
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +55 -15
- data/pg.gemspec +4 -2
- data/rakelib/task_extension.rb +1 -1
- data/translation/.po4a-version +7 -0
- data/translation/po/all.pot +910 -0
- data/translation/po/ja.po +1047 -0
- data/translation/po4a.cfg +12 -0
- data.tar.gz.sig +0 -0
- metadata +109 -34
- metadata.gz.sig +0 -0
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -233
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- 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
|
|
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
|
-
|
|
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
|
|
262
|
-
this->notice_receiver
|
|
263
|
-
this->notice_processor
|
|
264
|
-
this->type_map_for_queries
|
|
265
|
-
this->type_map_for_results
|
|
266
|
-
this->encoder_for_put_copy_data
|
|
267
|
-
this->decoder_for_get_copy_data
|
|
268
|
-
this->trace_stream
|
|
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
|
-
|
|
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
|
|
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
|
|
@@ -1811,6 +1815,7 @@ pgconn_set_single_row_mode(VALUE self)
|
|
|
1811
1815
|
{
|
|
1812
1816
|
PGconn *conn = pg_get_pgconn(self);
|
|
1813
1817
|
|
|
1818
|
+
rb_check_frozen(self);
|
|
1814
1819
|
if( PQsetSingleRowMode(conn) == 0 )
|
|
1815
1820
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
1816
1821
|
|
|
@@ -2145,6 +2150,7 @@ pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
|
|
2145
2150
|
{
|
|
2146
2151
|
int arg;
|
|
2147
2152
|
PGconn *conn = pg_get_pgconn(self);
|
|
2153
|
+
rb_check_frozen(self);
|
|
2148
2154
|
if(state == Qtrue)
|
|
2149
2155
|
arg = 1;
|
|
2150
2156
|
else if (state == Qfalse)
|
|
@@ -2443,8 +2449,9 @@ pgconn_async_flush(VALUE self)
|
|
|
2443
2449
|
VALUE socket_io = pgconn_socket_io(self);
|
|
2444
2450
|
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
|
2445
2451
|
|
|
2446
|
-
if (events & PG_RUBY_IO_READABLE)
|
|
2452
|
+
if (events & PG_RUBY_IO_READABLE){
|
|
2447
2453
|
pgconn_consume_input(self);
|
|
2454
|
+
}
|
|
2448
2455
|
}
|
|
2449
2456
|
return Qtrue;
|
|
2450
2457
|
}
|
|
@@ -2460,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
|
|
|
2460
2467
|
static VALUE
|
|
2461
2468
|
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
|
2462
2469
|
t_pg_connection *conn = pg_get_connection(self);
|
|
2470
|
+
rb_check_frozen(self);
|
|
2463
2471
|
conn->flush_data = RTEST(enabled);
|
|
2464
2472
|
return enabled;
|
|
2465
2473
|
}
|
|
@@ -2714,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
|
2714
2722
|
VALUE new_file;
|
|
2715
2723
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2716
2724
|
|
|
2725
|
+
rb_check_frozen(self);
|
|
2717
2726
|
if(!rb_respond_to(stream,rb_intern("fileno")))
|
|
2718
2727
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
|
2719
2728
|
|
|
@@ -2735,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
|
2735
2744
|
rb_raise(rb_eArgError, "stream is not writable");
|
|
2736
2745
|
|
|
2737
2746
|
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
|
2738
|
-
this->trace_stream
|
|
2747
|
+
RB_OBJ_WRITE(self, &this->trace_stream, new_file);
|
|
2739
2748
|
|
|
2740
2749
|
PQtrace(this->pgconn, new_fp);
|
|
2741
2750
|
return Qnil;
|
|
@@ -2754,7 +2763,7 @@ pgconn_untrace(VALUE self)
|
|
|
2754
2763
|
|
|
2755
2764
|
PQuntrace(this->pgconn);
|
|
2756
2765
|
rb_funcall(this->trace_stream, rb_intern("close"), 0);
|
|
2757
|
-
this->trace_stream
|
|
2766
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
|
2758
2767
|
return Qnil;
|
|
2759
2768
|
}
|
|
2760
2769
|
|
|
@@ -2813,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
|
|
|
2813
2822
|
VALUE proc, old_proc;
|
|
2814
2823
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2815
2824
|
|
|
2825
|
+
rb_check_frozen(self);
|
|
2816
2826
|
/* If default_notice_receiver is unset, assume that the current
|
|
2817
2827
|
* notice receiver is the default, and save it to a global variable.
|
|
2818
2828
|
* This should not be a problem because the default receiver is
|
|
2819
2829
|
* always the same, so won't vary among connections.
|
|
2820
2830
|
*/
|
|
2821
|
-
if(default_notice_receiver == NULL)
|
|
2822
|
-
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);
|
|
2823
2833
|
|
|
2824
2834
|
old_proc = this->notice_receiver;
|
|
2825
2835
|
if( rb_block_given_p() ) {
|
|
@@ -2828,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
|
|
|
2828
2838
|
} else {
|
|
2829
2839
|
/* if no block is given, set back to default */
|
|
2830
2840
|
proc = Qnil;
|
|
2831
|
-
PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
|
|
2841
|
+
PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
|
|
2832
2842
|
}
|
|
2833
2843
|
|
|
2834
|
-
this->notice_receiver
|
|
2844
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, proc);
|
|
2835
2845
|
return old_proc;
|
|
2836
2846
|
}
|
|
2837
2847
|
|
|
@@ -2846,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
|
|
|
2846
2856
|
VALUE self = (VALUE)arg;
|
|
2847
2857
|
t_pg_connection *this = pg_get_connection( self );
|
|
2848
2858
|
|
|
2849
|
-
if (this->
|
|
2859
|
+
if (this->notice_processor != Qnil) {
|
|
2850
2860
|
VALUE message_str = rb_str_new2(message);
|
|
2851
2861
|
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
|
2852
|
-
rb_funcall(this->
|
|
2862
|
+
rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
|
|
2853
2863
|
}
|
|
2854
2864
|
return;
|
|
2855
2865
|
}
|
|
@@ -2873,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
|
|
|
2873
2883
|
VALUE proc, old_proc;
|
|
2874
2884
|
t_pg_connection *this = pg_get_connection_safe( self );
|
|
2875
2885
|
|
|
2886
|
+
rb_check_frozen(self);
|
|
2876
2887
|
/* If default_notice_processor is unset, assume that the current
|
|
2877
2888
|
* notice processor is the default, and save it to a global variable.
|
|
2878
2889
|
* This should not be a problem because the default processor is
|
|
2879
2890
|
* always the same, so won't vary among connections.
|
|
2880
2891
|
*/
|
|
2881
|
-
if(default_notice_processor == NULL)
|
|
2882
|
-
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);
|
|
2883
2894
|
|
|
2884
|
-
old_proc = this->
|
|
2895
|
+
old_proc = this->notice_processor;
|
|
2885
2896
|
if( rb_block_given_p() ) {
|
|
2886
2897
|
proc = rb_block_proc();
|
|
2887
2898
|
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
|
|
2888
2899
|
} else {
|
|
2889
2900
|
/* if no block is given, set back to default */
|
|
2890
2901
|
proc = Qnil;
|
|
2891
|
-
PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
|
|
2902
|
+
PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
|
|
2892
2903
|
}
|
|
2893
2904
|
|
|
2894
|
-
this->
|
|
2905
|
+
RB_OBJ_WRITE(self, &this->notice_processor, proc);
|
|
2895
2906
|
return old_proc;
|
|
2896
2907
|
}
|
|
2897
2908
|
|
|
@@ -2923,6 +2934,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
|
2923
2934
|
{
|
|
2924
2935
|
PGconn *conn = pg_get_pgconn( self );
|
|
2925
2936
|
|
|
2937
|
+
rb_check_frozen(self);
|
|
2926
2938
|
Check_Type(str, T_STRING);
|
|
2927
2939
|
|
|
2928
2940
|
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
|
@@ -3091,7 +3103,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
|
3091
3103
|
VALUE rb_pgresult = Qnil;
|
|
3092
3104
|
PGresult *cur, *prev;
|
|
3093
3105
|
|
|
3094
|
-
|
|
3106
|
+
cur = prev = NULL;
|
|
3095
3107
|
for(;;) {
|
|
3096
3108
|
int status;
|
|
3097
3109
|
|
|
@@ -3123,8 +3135,14 @@ pgconn_async_get_last_result(VALUE self)
|
|
|
3123
3135
|
* conn.discard_results()
|
|
3124
3136
|
*
|
|
3125
3137
|
* Silently discard any prior query result that application didn't eat.
|
|
3126
|
-
* This is
|
|
3127
|
-
*
|
|
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
|
+
*
|
|
3128
3146
|
*/
|
|
3129
3147
|
static VALUE
|
|
3130
3148
|
pgconn_discard_results(VALUE self)
|
|
@@ -3132,8 +3150,12 @@ pgconn_discard_results(VALUE self)
|
|
|
3132
3150
|
PGconn *conn = pg_get_pgconn(self);
|
|
3133
3151
|
VALUE socket_io;
|
|
3134
3152
|
|
|
3135
|
-
|
|
3136
|
-
|
|
3153
|
+
switch( PQtransactionStatus(conn) ) {
|
|
3154
|
+
case PQTRANS_IDLE:
|
|
3155
|
+
case PQTRANS_INTRANS:
|
|
3156
|
+
case PQTRANS_INERROR:
|
|
3157
|
+
return Qnil;
|
|
3158
|
+
default:;
|
|
3137
3159
|
}
|
|
3138
3160
|
|
|
3139
3161
|
socket_io = pgconn_socket_io(self);
|
|
@@ -3146,10 +3168,21 @@ pgconn_discard_results(VALUE self)
|
|
|
3146
3168
|
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
|
3147
3169
|
*/
|
|
3148
3170
|
while( gvl_PQisBusy(conn) ){
|
|
3149
|
-
|
|
3150
|
-
|
|
3151
|
-
|
|
3152
|
-
|
|
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;
|
|
3153
3186
|
}
|
|
3154
3187
|
}
|
|
3155
3188
|
|
|
@@ -3159,7 +3192,9 @@ pgconn_discard_results(VALUE self)
|
|
|
3159
3192
|
status = PQresultStatus(cur);
|
|
3160
3193
|
PQclear(cur);
|
|
3161
3194
|
if (status == PGRES_COPY_IN){
|
|
3162
|
-
gvl_PQputCopyEnd(conn, "COPY terminated by new
|
|
3195
|
+
while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
|
|
3196
|
+
pgconn_async_flush(self);
|
|
3197
|
+
}
|
|
3163
3198
|
}
|
|
3164
3199
|
if (status == PGRES_COPY_OUT){
|
|
3165
3200
|
for(;;) {
|
|
@@ -3168,10 +3203,7 @@ pgconn_discard_results(VALUE self)
|
|
|
3168
3203
|
if( st == 0 ) {
|
|
3169
3204
|
/* would block -> wait for readable data */
|
|
3170
3205
|
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
|
3171
|
-
if ( PQconsumeInput(conn) == 0 )
|
|
3172
|
-
pgconn_close_socket_io(self);
|
|
3173
|
-
return Qfalse;
|
|
3174
|
-
}
|
|
3206
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
|
3175
3207
|
} else if( st > 0 ) {
|
|
3176
3208
|
/* some data retrieved -> discard it */
|
|
3177
3209
|
PQfreemem(buffer);
|
|
@@ -3184,6 +3216,10 @@ pgconn_discard_results(VALUE self)
|
|
|
3184
3216
|
}
|
|
3185
3217
|
|
|
3186
3218
|
return Qtrue;
|
|
3219
|
+
|
|
3220
|
+
error:
|
|
3221
|
+
pgconn_close_socket_io(self);
|
|
3222
|
+
return Qfalse;
|
|
3187
3223
|
}
|
|
3188
3224
|
|
|
3189
3225
|
/*
|
|
@@ -3640,6 +3676,14 @@ pgconn_send_flush_request(VALUE self)
|
|
|
3640
3676
|
* LARGE OBJECT SUPPORT
|
|
3641
3677
|
**************************************************************************/
|
|
3642
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
|
+
|
|
3643
3687
|
/*
|
|
3644
3688
|
* call-seq:
|
|
3645
3689
|
* conn.lo_creat( [mode] ) -> Integer
|
|
@@ -3660,7 +3704,10 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
|
3660
3704
|
else
|
|
3661
3705
|
mode = NUM2INT(nmode);
|
|
3662
3706
|
|
|
3663
|
-
|
|
3707
|
+
BLOCKING_BEGIN(conn)
|
|
3708
|
+
lo_oid = lo_creat(conn, mode);
|
|
3709
|
+
BLOCKING_END(conn)
|
|
3710
|
+
|
|
3664
3711
|
if (lo_oid == 0)
|
|
3665
3712
|
pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
|
|
3666
3713
|
|
|
@@ -3705,7 +3752,10 @@ pgconn_loimport(VALUE self, VALUE filename)
|
|
|
3705
3752
|
|
|
3706
3753
|
Check_Type(filename, T_STRING);
|
|
3707
3754
|
|
|
3708
|
-
|
|
3755
|
+
BLOCKING_BEGIN(conn)
|
|
3756
|
+
lo_oid = lo_import(conn, StringValueCStr(filename));
|
|
3757
|
+
BLOCKING_END(conn)
|
|
3758
|
+
|
|
3709
3759
|
if (lo_oid == 0) {
|
|
3710
3760
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3711
3761
|
}
|
|
@@ -3723,11 +3773,16 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
|
3723
3773
|
{
|
|
3724
3774
|
PGconn *conn = pg_get_pgconn(self);
|
|
3725
3775
|
Oid oid;
|
|
3776
|
+
int ret;
|
|
3726
3777
|
Check_Type(filename, T_STRING);
|
|
3727
3778
|
|
|
3728
3779
|
oid = NUM2UINT(lo_oid);
|
|
3729
3780
|
|
|
3730
|
-
|
|
3781
|
+
BLOCKING_BEGIN(conn)
|
|
3782
|
+
ret = lo_export(conn, oid, StringValueCStr(filename));
|
|
3783
|
+
BLOCKING_END(conn)
|
|
3784
|
+
|
|
3785
|
+
if (ret < 0) {
|
|
3731
3786
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
|
3732
3787
|
}
|
|
3733
3788
|
return Qnil;
|
|
@@ -3758,7 +3813,11 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
|
3758
3813
|
else
|
|
3759
3814
|
mode = NUM2INT(nmode);
|
|
3760
3815
|
|
|
3761
|
-
|
|
3816
|
+
BLOCKING_BEGIN(conn)
|
|
3817
|
+
fd = lo_open(conn, lo_oid, mode);
|
|
3818
|
+
BLOCKING_END(conn)
|
|
3819
|
+
|
|
3820
|
+
if(fd < 0) {
|
|
3762
3821
|
pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
|
|
3763
3822
|
}
|
|
3764
3823
|
return INT2FIX(fd);
|
|
@@ -3783,8 +3842,12 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
|
3783
3842
|
if( RSTRING_LEN(buffer) < 0) {
|
|
3784
3843
|
pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
|
|
3785
3844
|
}
|
|
3786
|
-
|
|
3787
|
-
|
|
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) {
|
|
3788
3851
|
pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
|
|
3789
3852
|
}
|
|
3790
3853
|
|
|
@@ -3812,7 +3875,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
|
3812
3875
|
pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
|
|
3813
3876
|
|
|
3814
3877
|
buffer = ALLOC_N(char, len);
|
|
3815
|
-
|
|
3878
|
+
|
|
3879
|
+
BLOCKING_BEGIN(conn)
|
|
3880
|
+
ret = lo_read(conn, lo_desc, buffer, len);
|
|
3881
|
+
BLOCKING_END(conn)
|
|
3882
|
+
|
|
3883
|
+
if(ret < 0)
|
|
3816
3884
|
pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
|
|
3817
3885
|
|
|
3818
3886
|
if(ret == 0) {
|
|
@@ -3842,7 +3910,11 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
|
3842
3910
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3843
3911
|
int ret;
|
|
3844
3912
|
|
|
3845
|
-
|
|
3913
|
+
BLOCKING_BEGIN(conn)
|
|
3914
|
+
ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
|
|
3915
|
+
BLOCKING_END(conn)
|
|
3916
|
+
|
|
3917
|
+
if(ret < 0) {
|
|
3846
3918
|
pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
|
|
3847
3919
|
}
|
|
3848
3920
|
|
|
@@ -3862,7 +3934,11 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
|
|
3862
3934
|
PGconn *conn = pg_get_pgconn(self);
|
|
3863
3935
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3864
3936
|
|
|
3865
|
-
|
|
3937
|
+
BLOCKING_BEGIN(conn)
|
|
3938
|
+
position = lo_tell(conn, lo_desc);
|
|
3939
|
+
BLOCKING_END(conn)
|
|
3940
|
+
|
|
3941
|
+
if(position < 0)
|
|
3866
3942
|
pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
|
|
3867
3943
|
|
|
3868
3944
|
return INT2FIX(position);
|
|
@@ -3880,8 +3956,13 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
|
3880
3956
|
PGconn *conn = pg_get_pgconn(self);
|
|
3881
3957
|
int lo_desc = NUM2INT(in_lo_desc);
|
|
3882
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)
|
|
3883
3964
|
|
|
3884
|
-
if(
|
|
3965
|
+
if(ret < 0)
|
|
3885
3966
|
pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
|
|
3886
3967
|
|
|
3887
3968
|
return Qnil;
|
|
@@ -3898,8 +3979,13 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
|
|
3898
3979
|
{
|
|
3899
3980
|
PGconn *conn = pg_get_pgconn(self);
|
|
3900
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)
|
|
3901
3987
|
|
|
3902
|
-
if(
|
|
3988
|
+
if(ret < 0)
|
|
3903
3989
|
pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
|
|
3904
3990
|
|
|
3905
3991
|
return Qnil;
|
|
@@ -3916,8 +4002,13 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
|
3916
4002
|
{
|
|
3917
4003
|
PGconn *conn = pg_get_pgconn(self);
|
|
3918
4004
|
Oid oid = NUM2UINT(in_oid);
|
|
4005
|
+
int ret;
|
|
4006
|
+
|
|
4007
|
+
BLOCKING_BEGIN(conn)
|
|
4008
|
+
ret = lo_unlink(conn,oid);
|
|
4009
|
+
BLOCKING_END(conn)
|
|
3919
4010
|
|
|
3920
|
-
if(
|
|
4011
|
+
if(ret < 0)
|
|
3921
4012
|
pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
|
|
3922
4013
|
|
|
3923
4014
|
return Qnil;
|
|
@@ -3975,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
|
3975
4066
|
static VALUE
|
|
3976
4067
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
|
3977
4068
|
{
|
|
4069
|
+
rb_check_frozen(self);
|
|
3978
4070
|
if (NIL_P(enc)) {
|
|
3979
4071
|
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
|
3980
4072
|
return enc;
|
|
@@ -4029,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
|
4029
4121
|
{
|
|
4030
4122
|
VALUE query_format, query;
|
|
4031
4123
|
|
|
4124
|
+
rb_check_frozen(self);
|
|
4032
4125
|
Check_Type(encname, T_STRING);
|
|
4033
4126
|
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
|
4034
4127
|
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
|
@@ -4081,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
|
|
|
4081
4174
|
rb_encoding *enc;
|
|
4082
4175
|
const char *encname;
|
|
4083
4176
|
|
|
4177
|
+
rb_check_frozen(self);
|
|
4084
4178
|
if (( enc = rb_default_internal_encoding() )) {
|
|
4085
4179
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
|
4086
4180
|
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
|
@@ -4110,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
|
4110
4204
|
t_typemap *tm;
|
|
4111
4205
|
UNUSED(tm);
|
|
4112
4206
|
|
|
4207
|
+
rb_check_frozen(self);
|
|
4113
4208
|
/* Check type of method param */
|
|
4114
4209
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
|
4115
4210
|
|
|
4116
|
-
this->type_map_for_queries
|
|
4211
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
|
|
4117
4212
|
|
|
4118
4213
|
return typemap;
|
|
4119
4214
|
}
|
|
@@ -4150,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
|
4150
4245
|
t_typemap *tm;
|
|
4151
4246
|
UNUSED(tm);
|
|
4152
4247
|
|
|
4248
|
+
rb_check_frozen(self);
|
|
4153
4249
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
|
4154
|
-
this->type_map_for_results
|
|
4250
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
|
|
4155
4251
|
|
|
4156
4252
|
return typemap;
|
|
4157
4253
|
}
|
|
@@ -4189,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
|
4189
4285
|
{
|
|
4190
4286
|
t_pg_connection *this = pg_get_connection( self );
|
|
4191
4287
|
|
|
4288
|
+
rb_check_frozen(self);
|
|
4192
4289
|
if( encoder != Qnil ){
|
|
4193
4290
|
t_pg_coder *co;
|
|
4194
4291
|
UNUSED(co);
|
|
4195
4292
|
/* Check argument type */
|
|
4196
4293
|
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
|
4197
4294
|
}
|
|
4198
|
-
this->encoder_for_put_copy_data
|
|
4295
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
|
|
4199
4296
|
|
|
4200
4297
|
return encoder;
|
|
4201
4298
|
}
|
|
@@ -4237,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
|
4237
4334
|
{
|
|
4238
4335
|
t_pg_connection *this = pg_get_connection( self );
|
|
4239
4336
|
|
|
4337
|
+
rb_check_frozen(self);
|
|
4240
4338
|
if( decoder != Qnil ){
|
|
4241
4339
|
t_pg_coder *co;
|
|
4242
4340
|
UNUSED(co);
|
|
4243
4341
|
/* Check argument type */
|
|
4244
4342
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
|
4245
4343
|
}
|
|
4246
|
-
this->decoder_for_get_copy_data
|
|
4344
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
|
|
4247
4345
|
|
|
4248
4346
|
return decoder;
|
|
4249
4347
|
}
|
|
@@ -4289,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
|
4289
4387
|
{
|
|
4290
4388
|
t_pg_connection *this = pg_get_connection( self );
|
|
4291
4389
|
|
|
4390
|
+
rb_check_frozen(self);
|
|
4292
4391
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
|
4293
4392
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
|
4294
4393
|
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|