pg 1.4.1 → 1.5.6
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 +45 -14
- data/.github/workflows/source-gem.yml +35 -23
- data/.gitignore +11 -2
- data/.travis.yml +2 -2
- data/Gemfile +3 -0
- data/{History.rdoc → History.md} +285 -140
- data/README.ja.md +300 -0
- data/README.md +286 -0
- data/Rakefile +18 -6
- data/Rakefile.cross +8 -11
- data/certs/kanis@comcard.de.pem +20 -0
- data/certs/larskanis-2023.pem +24 -0
- data/certs/larskanis-2024.pem +24 -0
- data/ext/errorcodes.def +4 -0
- data/ext/errorcodes.txt +2 -1
- data/ext/extconf.rb +4 -0
- data/ext/pg.c +15 -55
- data/ext/pg.h +11 -6
- 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 +201 -73
- 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 +19 -10
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +35 -33
- 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 +186 -104
- 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 +5 -3
- data/rakelib/task_extension.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +96 -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,15 @@ 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);
|
266
|
+
rb_ivar_set(self, rb_intern("@calls_to_put_copy_data"), INT2FIX(0));
|
269
267
|
|
270
268
|
return self;
|
271
269
|
}
|
@@ -565,6 +563,27 @@ pgconn_sync_reset( VALUE self )
|
|
565
563
|
return self;
|
566
564
|
}
|
567
565
|
|
566
|
+
static VALUE
|
567
|
+
pgconn_reset_start2( VALUE self, VALUE conninfo )
|
568
|
+
{
|
569
|
+
t_pg_connection *this = pg_get_connection( self );
|
570
|
+
|
571
|
+
/* Close old connection */
|
572
|
+
pgconn_close_socket_io( self );
|
573
|
+
PQfinish( this->pgconn );
|
574
|
+
|
575
|
+
/* Start new connection */
|
576
|
+
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
577
|
+
|
578
|
+
if( this->pgconn == NULL )
|
579
|
+
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
580
|
+
|
581
|
+
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
582
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
|
583
|
+
|
584
|
+
return Qnil;
|
585
|
+
}
|
586
|
+
|
568
587
|
/*
|
569
588
|
* call-seq:
|
570
589
|
* conn.reset_start() -> nil
|
@@ -701,7 +720,10 @@ static VALUE
|
|
701
720
|
pgconn_port(VALUE self)
|
702
721
|
{
|
703
722
|
char* port = PQport(pg_get_pgconn(self));
|
704
|
-
|
723
|
+
if (!port || port[0] == '\0')
|
724
|
+
return INT2NUM(DEF_PGPORT);
|
725
|
+
else
|
726
|
+
return INT2NUM(atoi(port));
|
705
727
|
}
|
706
728
|
|
707
729
|
/*
|
@@ -762,6 +784,10 @@ pgconn_conninfo( VALUE self )
|
|
762
784
|
*
|
763
785
|
* ... and other constants of kind PG::Constants::CONNECTION_*
|
764
786
|
*
|
787
|
+
* This method returns the status of the last command from memory.
|
788
|
+
* It doesn't do any socket access hence is not suitable to test the connectivity.
|
789
|
+
* See check_socket for a way to verify the socket state.
|
790
|
+
*
|
765
791
|
* Example:
|
766
792
|
* PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
|
767
793
|
*/
|
@@ -937,7 +963,7 @@ pgconn_socket_io(VALUE self)
|
|
937
963
|
/* Disable autoclose feature */
|
938
964
|
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
939
965
|
|
940
|
-
this->socket_io
|
966
|
+
RB_OBJ_WRITE(self, &this->socket_io, socket_io);
|
941
967
|
}
|
942
968
|
|
943
969
|
return socket_io;
|
@@ -1154,7 +1180,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1154
1180
|
},
|
1155
1181
|
0,
|
1156
1182
|
0,
|
1157
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1183
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1158
1184
|
};
|
1159
1185
|
|
1160
1186
|
static char *
|
@@ -1187,7 +1213,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1187
1213
|
},
|
1188
1214
|
0,
|
1189
1215
|
0,
|
1190
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1216
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1191
1217
|
};
|
1192
1218
|
|
1193
1219
|
static int
|
@@ -1526,8 +1552,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1526
1552
|
* It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
|
1527
1553
|
*/
|
1528
1554
|
static VALUE
|
1529
|
-
pgconn_sync_describe_portal(self, stmt_name)
|
1530
|
-
VALUE self, stmt_name;
|
1555
|
+
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
1531
1556
|
{
|
1532
1557
|
PGresult *result;
|
1533
1558
|
VALUE rb_pgresult;
|
@@ -1811,6 +1836,7 @@ pgconn_set_single_row_mode(VALUE self)
|
|
1811
1836
|
{
|
1812
1837
|
PGconn *conn = pg_get_pgconn(self);
|
1813
1838
|
|
1839
|
+
rb_check_frozen(self);
|
1814
1840
|
if( PQsetSingleRowMode(conn) == 0 )
|
1815
1841
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
1816
1842
|
|
@@ -2145,6 +2171,7 @@ pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
|
2145
2171
|
{
|
2146
2172
|
int arg;
|
2147
2173
|
PGconn *conn = pg_get_pgconn(self);
|
2174
|
+
rb_check_frozen(self);
|
2148
2175
|
if(state == Qtrue)
|
2149
2176
|
arg = 1;
|
2150
2177
|
else if (state == Qfalse)
|
@@ -2443,8 +2470,9 @@ pgconn_async_flush(VALUE self)
|
|
2443
2470
|
VALUE socket_io = pgconn_socket_io(self);
|
2444
2471
|
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
2445
2472
|
|
2446
|
-
if (events & PG_RUBY_IO_READABLE)
|
2473
|
+
if (events & PG_RUBY_IO_READABLE){
|
2447
2474
|
pgconn_consume_input(self);
|
2475
|
+
}
|
2448
2476
|
}
|
2449
2477
|
return Qtrue;
|
2450
2478
|
}
|
@@ -2460,6 +2488,7 @@ pgconn_wait_for_flush( VALUE self ){
|
|
2460
2488
|
static VALUE
|
2461
2489
|
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2462
2490
|
t_pg_connection *conn = pg_get_connection(self);
|
2491
|
+
rb_check_frozen(self);
|
2463
2492
|
conn->flush_data = RTEST(enabled);
|
2464
2493
|
return enabled;
|
2465
2494
|
}
|
@@ -2714,6 +2743,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2714
2743
|
VALUE new_file;
|
2715
2744
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2716
2745
|
|
2746
|
+
rb_check_frozen(self);
|
2717
2747
|
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2718
2748
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2719
2749
|
|
@@ -2735,7 +2765,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2735
2765
|
rb_raise(rb_eArgError, "stream is not writable");
|
2736
2766
|
|
2737
2767
|
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2738
|
-
this->trace_stream
|
2768
|
+
RB_OBJ_WRITE(self, &this->trace_stream, new_file);
|
2739
2769
|
|
2740
2770
|
PQtrace(this->pgconn, new_fp);
|
2741
2771
|
return Qnil;
|
@@ -2754,7 +2784,7 @@ pgconn_untrace(VALUE self)
|
|
2754
2784
|
|
2755
2785
|
PQuntrace(this->pgconn);
|
2756
2786
|
rb_funcall(this->trace_stream, rb_intern("close"), 0);
|
2757
|
-
this->trace_stream
|
2787
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
2758
2788
|
return Qnil;
|
2759
2789
|
}
|
2760
2790
|
|
@@ -2813,13 +2843,14 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2813
2843
|
VALUE proc, old_proc;
|
2814
2844
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2815
2845
|
|
2846
|
+
rb_check_frozen(self);
|
2816
2847
|
/* If default_notice_receiver is unset, assume that the current
|
2817
2848
|
* notice receiver is the default, and save it to a global variable.
|
2818
2849
|
* This should not be a problem because the default receiver is
|
2819
2850
|
* always the same, so won't vary among connections.
|
2820
2851
|
*/
|
2821
|
-
if(default_notice_receiver == NULL)
|
2822
|
-
default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
|
2852
|
+
if(this->default_notice_receiver == NULL)
|
2853
|
+
this->default_notice_receiver = PQsetNoticeReceiver(this->pgconn, NULL, NULL);
|
2823
2854
|
|
2824
2855
|
old_proc = this->notice_receiver;
|
2825
2856
|
if( rb_block_given_p() ) {
|
@@ -2828,10 +2859,10 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2828
2859
|
} else {
|
2829
2860
|
/* if no block is given, set back to default */
|
2830
2861
|
proc = Qnil;
|
2831
|
-
PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
|
2862
|
+
PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
|
2832
2863
|
}
|
2833
2864
|
|
2834
|
-
this->notice_receiver
|
2865
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, proc);
|
2835
2866
|
return old_proc;
|
2836
2867
|
}
|
2837
2868
|
|
@@ -2846,10 +2877,10 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2846
2877
|
VALUE self = (VALUE)arg;
|
2847
2878
|
t_pg_connection *this = pg_get_connection( self );
|
2848
2879
|
|
2849
|
-
if (this->
|
2880
|
+
if (this->notice_processor != Qnil) {
|
2850
2881
|
VALUE message_str = rb_str_new2(message);
|
2851
2882
|
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2852
|
-
rb_funcall(this->
|
2883
|
+
rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
|
2853
2884
|
}
|
2854
2885
|
return;
|
2855
2886
|
}
|
@@ -2873,25 +2904,26 @@ pgconn_set_notice_processor(VALUE self)
|
|
2873
2904
|
VALUE proc, old_proc;
|
2874
2905
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2875
2906
|
|
2907
|
+
rb_check_frozen(self);
|
2876
2908
|
/* If default_notice_processor is unset, assume that the current
|
2877
2909
|
* notice processor is the default, and save it to a global variable.
|
2878
2910
|
* This should not be a problem because the default processor is
|
2879
2911
|
* always the same, so won't vary among connections.
|
2880
2912
|
*/
|
2881
|
-
if(default_notice_processor == NULL)
|
2882
|
-
default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
|
2913
|
+
if(this->default_notice_processor == NULL)
|
2914
|
+
this->default_notice_processor = PQsetNoticeProcessor(this->pgconn, NULL, NULL);
|
2883
2915
|
|
2884
|
-
old_proc = this->
|
2916
|
+
old_proc = this->notice_processor;
|
2885
2917
|
if( rb_block_given_p() ) {
|
2886
2918
|
proc = rb_block_proc();
|
2887
2919
|
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
|
2888
2920
|
} else {
|
2889
2921
|
/* if no block is given, set back to default */
|
2890
2922
|
proc = Qnil;
|
2891
|
-
PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
|
2923
|
+
PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
|
2892
2924
|
}
|
2893
2925
|
|
2894
|
-
this->
|
2926
|
+
RB_OBJ_WRITE(self, &this->notice_processor, proc);
|
2895
2927
|
return old_proc;
|
2896
2928
|
}
|
2897
2929
|
|
@@ -2923,6 +2955,7 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2923
2955
|
{
|
2924
2956
|
PGconn *conn = pg_get_pgconn( self );
|
2925
2957
|
|
2958
|
+
rb_check_frozen(self);
|
2926
2959
|
Check_Type(str, T_STRING);
|
2927
2960
|
|
2928
2961
|
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
@@ -3091,7 +3124,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
3091
3124
|
VALUE rb_pgresult = Qnil;
|
3092
3125
|
PGresult *cur, *prev;
|
3093
3126
|
|
3094
|
-
|
3127
|
+
cur = prev = NULL;
|
3095
3128
|
for(;;) {
|
3096
3129
|
int status;
|
3097
3130
|
|
@@ -3123,8 +3156,14 @@ pgconn_async_get_last_result(VALUE self)
|
|
3123
3156
|
* conn.discard_results()
|
3124
3157
|
*
|
3125
3158
|
* Silently discard any prior query result that application didn't eat.
|
3126
|
-
* This is
|
3127
|
-
*
|
3159
|
+
* This is internally used prior to Connection#exec and sibling methods.
|
3160
|
+
* It doesn't raise an exception on connection errors, but returns +false+ instead.
|
3161
|
+
*
|
3162
|
+
* Returns:
|
3163
|
+
* * +nil+ when the connection is already idle
|
3164
|
+
* * +true+ when some results have been discarded
|
3165
|
+
* * +false+ when a failure occured and the connection was closed
|
3166
|
+
*
|
3128
3167
|
*/
|
3129
3168
|
static VALUE
|
3130
3169
|
pgconn_discard_results(VALUE self)
|
@@ -3132,8 +3171,12 @@ pgconn_discard_results(VALUE self)
|
|
3132
3171
|
PGconn *conn = pg_get_pgconn(self);
|
3133
3172
|
VALUE socket_io;
|
3134
3173
|
|
3135
|
-
|
3136
|
-
|
3174
|
+
switch( PQtransactionStatus(conn) ) {
|
3175
|
+
case PQTRANS_IDLE:
|
3176
|
+
case PQTRANS_INTRANS:
|
3177
|
+
case PQTRANS_INERROR:
|
3178
|
+
return Qnil;
|
3179
|
+
default:;
|
3137
3180
|
}
|
3138
3181
|
|
3139
3182
|
socket_io = pgconn_socket_io(self);
|
@@ -3146,10 +3189,21 @@ pgconn_discard_results(VALUE self)
|
|
3146
3189
|
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
3147
3190
|
*/
|
3148
3191
|
while( gvl_PQisBusy(conn) ){
|
3149
|
-
|
3150
|
-
|
3151
|
-
|
3152
|
-
|
3192
|
+
int events;
|
3193
|
+
|
3194
|
+
switch( PQflush(conn) ) {
|
3195
|
+
case 1:
|
3196
|
+
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
3197
|
+
if (events & PG_RUBY_IO_READABLE){
|
3198
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
3199
|
+
}
|
3200
|
+
break;
|
3201
|
+
case 0:
|
3202
|
+
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3203
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
3204
|
+
break;
|
3205
|
+
default:
|
3206
|
+
goto error;
|
3153
3207
|
}
|
3154
3208
|
}
|
3155
3209
|
|
@@ -3159,7 +3213,9 @@ pgconn_discard_results(VALUE self)
|
|
3159
3213
|
status = PQresultStatus(cur);
|
3160
3214
|
PQclear(cur);
|
3161
3215
|
if (status == PGRES_COPY_IN){
|
3162
|
-
gvl_PQputCopyEnd(conn, "COPY terminated by new
|
3216
|
+
while( gvl_PQputCopyEnd(conn, "COPY terminated by new query or discard_results") == 0 ){
|
3217
|
+
pgconn_async_flush(self);
|
3218
|
+
}
|
3163
3219
|
}
|
3164
3220
|
if (status == PGRES_COPY_OUT){
|
3165
3221
|
for(;;) {
|
@@ -3168,10 +3224,7 @@ pgconn_discard_results(VALUE self)
|
|
3168
3224
|
if( st == 0 ) {
|
3169
3225
|
/* would block -> wait for readable data */
|
3170
3226
|
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
|
-
}
|
3227
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
3175
3228
|
} else if( st > 0 ) {
|
3176
3229
|
/* some data retrieved -> discard it */
|
3177
3230
|
PQfreemem(buffer);
|
@@ -3184,6 +3237,10 @@ pgconn_discard_results(VALUE self)
|
|
3184
3237
|
}
|
3185
3238
|
|
3186
3239
|
return Qtrue;
|
3240
|
+
|
3241
|
+
error:
|
3242
|
+
pgconn_close_socket_io(self);
|
3243
|
+
return Qfalse;
|
3187
3244
|
}
|
3188
3245
|
|
3189
3246
|
/*
|
@@ -3640,6 +3697,14 @@ pgconn_send_flush_request(VALUE self)
|
|
3640
3697
|
* LARGE OBJECT SUPPORT
|
3641
3698
|
**************************************************************************/
|
3642
3699
|
|
3700
|
+
#define BLOCKING_BEGIN(conn) do { \
|
3701
|
+
int old_nonblocking = PQisnonblocking(conn); \
|
3702
|
+
PQsetnonblocking(conn, 0);
|
3703
|
+
|
3704
|
+
#define BLOCKING_END(th) \
|
3705
|
+
PQsetnonblocking(conn, old_nonblocking); \
|
3706
|
+
} while(0);
|
3707
|
+
|
3643
3708
|
/*
|
3644
3709
|
* call-seq:
|
3645
3710
|
* conn.lo_creat( [mode] ) -> Integer
|
@@ -3660,7 +3725,10 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
3660
3725
|
else
|
3661
3726
|
mode = NUM2INT(nmode);
|
3662
3727
|
|
3663
|
-
|
3728
|
+
BLOCKING_BEGIN(conn)
|
3729
|
+
lo_oid = lo_creat(conn, mode);
|
3730
|
+
BLOCKING_END(conn)
|
3731
|
+
|
3664
3732
|
if (lo_oid == 0)
|
3665
3733
|
pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
|
3666
3734
|
|
@@ -3705,7 +3773,10 @@ pgconn_loimport(VALUE self, VALUE filename)
|
|
3705
3773
|
|
3706
3774
|
Check_Type(filename, T_STRING);
|
3707
3775
|
|
3708
|
-
|
3776
|
+
BLOCKING_BEGIN(conn)
|
3777
|
+
lo_oid = lo_import(conn, StringValueCStr(filename));
|
3778
|
+
BLOCKING_END(conn)
|
3779
|
+
|
3709
3780
|
if (lo_oid == 0) {
|
3710
3781
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3711
3782
|
}
|
@@ -3723,11 +3794,16 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
3723
3794
|
{
|
3724
3795
|
PGconn *conn = pg_get_pgconn(self);
|
3725
3796
|
Oid oid;
|
3797
|
+
int ret;
|
3726
3798
|
Check_Type(filename, T_STRING);
|
3727
3799
|
|
3728
3800
|
oid = NUM2UINT(lo_oid);
|
3729
3801
|
|
3730
|
-
|
3802
|
+
BLOCKING_BEGIN(conn)
|
3803
|
+
ret = lo_export(conn, oid, StringValueCStr(filename));
|
3804
|
+
BLOCKING_END(conn)
|
3805
|
+
|
3806
|
+
if (ret < 0) {
|
3731
3807
|
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3732
3808
|
}
|
3733
3809
|
return Qnil;
|
@@ -3758,7 +3834,11 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
3758
3834
|
else
|
3759
3835
|
mode = NUM2INT(nmode);
|
3760
3836
|
|
3761
|
-
|
3837
|
+
BLOCKING_BEGIN(conn)
|
3838
|
+
fd = lo_open(conn, lo_oid, mode);
|
3839
|
+
BLOCKING_END(conn)
|
3840
|
+
|
3841
|
+
if(fd < 0) {
|
3762
3842
|
pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
|
3763
3843
|
}
|
3764
3844
|
return INT2FIX(fd);
|
@@ -3783,8 +3863,12 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
3783
3863
|
if( RSTRING_LEN(buffer) < 0) {
|
3784
3864
|
pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
|
3785
3865
|
}
|
3786
|
-
|
3787
|
-
|
3866
|
+
BLOCKING_BEGIN(conn)
|
3867
|
+
n = lo_write(conn, fd, StringValuePtr(buffer),
|
3868
|
+
RSTRING_LEN(buffer));
|
3869
|
+
BLOCKING_END(conn)
|
3870
|
+
|
3871
|
+
if(n < 0) {
|
3788
3872
|
pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
|
3789
3873
|
}
|
3790
3874
|
|
@@ -3812,7 +3896,12 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3812
3896
|
pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
|
3813
3897
|
|
3814
3898
|
buffer = ALLOC_N(char, len);
|
3815
|
-
|
3899
|
+
|
3900
|
+
BLOCKING_BEGIN(conn)
|
3901
|
+
ret = lo_read(conn, lo_desc, buffer, len);
|
3902
|
+
BLOCKING_END(conn)
|
3903
|
+
|
3904
|
+
if(ret < 0)
|
3816
3905
|
pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
|
3817
3906
|
|
3818
3907
|
if(ret == 0) {
|
@@ -3842,7 +3931,11 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
3842
3931
|
int lo_desc = NUM2INT(in_lo_desc);
|
3843
3932
|
int ret;
|
3844
3933
|
|
3845
|
-
|
3934
|
+
BLOCKING_BEGIN(conn)
|
3935
|
+
ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
|
3936
|
+
BLOCKING_END(conn)
|
3937
|
+
|
3938
|
+
if(ret < 0) {
|
3846
3939
|
pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
|
3847
3940
|
}
|
3848
3941
|
|
@@ -3862,7 +3955,11 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
|
3862
3955
|
PGconn *conn = pg_get_pgconn(self);
|
3863
3956
|
int lo_desc = NUM2INT(in_lo_desc);
|
3864
3957
|
|
3865
|
-
|
3958
|
+
BLOCKING_BEGIN(conn)
|
3959
|
+
position = lo_tell(conn, lo_desc);
|
3960
|
+
BLOCKING_END(conn)
|
3961
|
+
|
3962
|
+
if(position < 0)
|
3866
3963
|
pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
|
3867
3964
|
|
3868
3965
|
return INT2FIX(position);
|
@@ -3880,8 +3977,13 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3880
3977
|
PGconn *conn = pg_get_pgconn(self);
|
3881
3978
|
int lo_desc = NUM2INT(in_lo_desc);
|
3882
3979
|
size_t len = NUM2INT(in_len);
|
3980
|
+
int ret;
|
3981
|
+
|
3982
|
+
BLOCKING_BEGIN(conn)
|
3983
|
+
ret = lo_truncate(conn,lo_desc,len);
|
3984
|
+
BLOCKING_END(conn)
|
3883
3985
|
|
3884
|
-
if(
|
3986
|
+
if(ret < 0)
|
3885
3987
|
pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
|
3886
3988
|
|
3887
3989
|
return Qnil;
|
@@ -3898,8 +4000,13 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
|
3898
4000
|
{
|
3899
4001
|
PGconn *conn = pg_get_pgconn(self);
|
3900
4002
|
int lo_desc = NUM2INT(in_lo_desc);
|
4003
|
+
int ret;
|
4004
|
+
|
4005
|
+
BLOCKING_BEGIN(conn)
|
4006
|
+
ret = lo_close(conn,lo_desc);
|
4007
|
+
BLOCKING_END(conn)
|
3901
4008
|
|
3902
|
-
if(
|
4009
|
+
if(ret < 0)
|
3903
4010
|
pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
|
3904
4011
|
|
3905
4012
|
return Qnil;
|
@@ -3916,8 +4023,13 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3916
4023
|
{
|
3917
4024
|
PGconn *conn = pg_get_pgconn(self);
|
3918
4025
|
Oid oid = NUM2UINT(in_oid);
|
4026
|
+
int ret;
|
4027
|
+
|
4028
|
+
BLOCKING_BEGIN(conn)
|
4029
|
+
ret = lo_unlink(conn,oid);
|
4030
|
+
BLOCKING_END(conn)
|
3919
4031
|
|
3920
|
-
if(
|
4032
|
+
if(ret < 0)
|
3921
4033
|
pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
|
3922
4034
|
|
3923
4035
|
return Qnil;
|
@@ -3975,6 +4087,7 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
3975
4087
|
static VALUE
|
3976
4088
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3977
4089
|
{
|
4090
|
+
rb_check_frozen(self);
|
3978
4091
|
if (NIL_P(enc)) {
|
3979
4092
|
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3980
4093
|
return enc;
|
@@ -4029,6 +4142,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4029
4142
|
{
|
4030
4143
|
VALUE query_format, query;
|
4031
4144
|
|
4145
|
+
rb_check_frozen(self);
|
4032
4146
|
Check_Type(encname, T_STRING);
|
4033
4147
|
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4034
4148
|
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
@@ -4078,15 +4192,23 @@ static VALUE
|
|
4078
4192
|
pgconn_set_default_encoding( VALUE self )
|
4079
4193
|
{
|
4080
4194
|
PGconn *conn = pg_get_pgconn( self );
|
4081
|
-
rb_encoding *
|
4082
|
-
|
4083
|
-
|
4084
|
-
if ((
|
4085
|
-
|
4086
|
-
|
4087
|
-
|
4088
|
-
|
4089
|
-
|
4195
|
+
rb_encoding *rb_enc;
|
4196
|
+
|
4197
|
+
rb_check_frozen(self);
|
4198
|
+
if (( rb_enc = rb_default_internal_encoding() )) {
|
4199
|
+
rb_encoding * conn_encoding = pg_conn_enc_get( conn );
|
4200
|
+
|
4201
|
+
/* Don't set the server encoding, if it's unnecessary.
|
4202
|
+
* This is important for connection proxies, who disallow configuration settings.
|
4203
|
+
*/
|
4204
|
+
if ( conn_encoding != rb_enc ) {
|
4205
|
+
const char *encname = pg_get_rb_encoding_as_pg_encoding( rb_enc );
|
4206
|
+
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
4207
|
+
rb_warning( "Failed to set the default_internal encoding to %s: '%s'",
|
4208
|
+
encname, PQerrorMessage(conn) );
|
4209
|
+
}
|
4210
|
+
pgconn_set_internal_encoding_index( self );
|
4211
|
+
return rb_enc_from_encoding( rb_enc );
|
4090
4212
|
} else {
|
4091
4213
|
pgconn_set_internal_encoding_index( self );
|
4092
4214
|
return Qnil;
|
@@ -4110,10 +4232,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
4110
4232
|
t_typemap *tm;
|
4111
4233
|
UNUSED(tm);
|
4112
4234
|
|
4235
|
+
rb_check_frozen(self);
|
4113
4236
|
/* Check type of method param */
|
4114
4237
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4115
4238
|
|
4116
|
-
this->type_map_for_queries
|
4239
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
|
4117
4240
|
|
4118
4241
|
return typemap;
|
4119
4242
|
}
|
@@ -4150,8 +4273,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
4150
4273
|
t_typemap *tm;
|
4151
4274
|
UNUSED(tm);
|
4152
4275
|
|
4276
|
+
rb_check_frozen(self);
|
4153
4277
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4154
|
-
this->type_map_for_results
|
4278
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
|
4155
4279
|
|
4156
4280
|
return typemap;
|
4157
4281
|
}
|
@@ -4189,13 +4313,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4189
4313
|
{
|
4190
4314
|
t_pg_connection *this = pg_get_connection( self );
|
4191
4315
|
|
4316
|
+
rb_check_frozen(self);
|
4192
4317
|
if( encoder != Qnil ){
|
4193
4318
|
t_pg_coder *co;
|
4194
4319
|
UNUSED(co);
|
4195
4320
|
/* Check argument type */
|
4196
4321
|
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4197
4322
|
}
|
4198
|
-
this->encoder_for_put_copy_data
|
4323
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
|
4199
4324
|
|
4200
4325
|
return encoder;
|
4201
4326
|
}
|
@@ -4237,13 +4362,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4237
4362
|
{
|
4238
4363
|
t_pg_connection *this = pg_get_connection( self );
|
4239
4364
|
|
4365
|
+
rb_check_frozen(self);
|
4240
4366
|
if( decoder != Qnil ){
|
4241
4367
|
t_pg_coder *co;
|
4242
4368
|
UNUSED(co);
|
4243
4369
|
/* Check argument type */
|
4244
4370
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4245
4371
|
}
|
4246
|
-
this->decoder_for_get_copy_data
|
4372
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
|
4247
4373
|
|
4248
4374
|
return decoder;
|
4249
4375
|
}
|
@@ -4289,6 +4415,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
4289
4415
|
{
|
4290
4416
|
t_pg_connection *this = pg_get_connection( self );
|
4291
4417
|
|
4418
|
+
rb_check_frozen(self);
|
4292
4419
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4293
4420
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4294
4421
|
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
@@ -4325,7 +4452,7 @@ pgconn_field_name_type_get(VALUE self)
|
|
4325
4452
|
* Document-class: PG::Connection
|
4326
4453
|
*/
|
4327
4454
|
void
|
4328
|
-
init_pg_connection()
|
4455
|
+
init_pg_connection(void)
|
4329
4456
|
{
|
4330
4457
|
s_id_encode = rb_intern("encode");
|
4331
4458
|
s_id_autoclose_set = rb_intern("autoclose=");
|
@@ -4362,6 +4489,7 @@ init_pg_connection()
|
|
4362
4489
|
rb_define_method(rb_cPGconn, "finished?", pgconn_finished_p, 0);
|
4363
4490
|
rb_define_method(rb_cPGconn, "sync_reset", pgconn_sync_reset, 0);
|
4364
4491
|
rb_define_method(rb_cPGconn, "reset_start", pgconn_reset_start, 0);
|
4492
|
+
rb_define_private_method(rb_cPGconn, "reset_start2", pgconn_reset_start2, 1);
|
4365
4493
|
rb_define_method(rb_cPGconn, "reset_poll", pgconn_reset_poll, 0);
|
4366
4494
|
rb_define_alias(rb_cPGconn, "close", "finish");
|
4367
4495
|
|