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.
- 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=");
|