pg 1.4.3 → 1.5.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +15 -9
- data/.github/workflows/binary-gems.yml +43 -12
- data/.github/workflows/source-gem.yml +28 -20
- data/.gitignore +11 -2
- data/.travis.yml +2 -2
- data/{History.rdoc → History.md} +251 -145
- data/README.ja.md +276 -0
- data/README.md +286 -0
- data/Rakefile +15 -6
- 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 +14 -30
- data/ext/pg.h +11 -5
- data/ext/pg_binary_decoder.c +80 -1
- data/ext/pg_binary_encoder.c +225 -1
- data/ext/pg_coder.c +17 -8
- data/ext/pg_connection.c +162 -64
- data/ext/pg_copy_coder.c +307 -18
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +6 -5
- data/ext/pg_result.c +102 -26
- data/ext/pg_text_decoder.c +28 -10
- data/ext/pg_text_encoder.c +23 -10
- data/ext/pg_tuple.c +35 -32
- data/ext/pg_type_map.c +4 -3
- data/ext/pg_type_map_all_strings.c +3 -3
- data/ext/pg_type_map_by_class.c +6 -4
- data/ext/pg_type_map_by_column.c +9 -5
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +8 -5
- data/ext/pg_type_map_in_ruby.c +6 -3
- 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 +148 -86
- 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 +101 -32
- metadata.gz.sig +0 -0
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -214
- 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
|
@@ -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
|
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
|
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
|
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->
|
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->
|
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->
|
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->
|
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
|
-
|
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
|
3128
|
-
*
|
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
|
-
|
3137
|
-
|
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
|
-
|
3151
|
-
|
3152
|
-
|
3153
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
3788
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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(
|
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(
|
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(
|
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
|
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
|
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
|
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
|
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=");
|