pg 1.3.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 +43 -12
- data/.github/workflows/source-gem.yml +28 -20
- data/.gitignore +11 -2
- data/.travis.yml +2 -2
- data/{History.rdoc → History.md} +293 -122
- 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 -54
- 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 +380 -250
- data/ext/pg_copy_coder.c +307 -18
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +12 -9
- data/ext/pg_result.c +104 -27
- 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 +36 -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 +265 -136
- data/lib/pg/exceptions.rb +14 -1
- 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 +59 -19
- 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,19 +16,37 @@ 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 );
|
25
22
|
static void pgconn_set_internal_encoding_index( VALUE );
|
26
23
|
static const rb_data_type_t pg_connection_type;
|
24
|
+
static VALUE pgconn_async_flush(VALUE self);
|
27
25
|
|
28
26
|
/*
|
29
27
|
* Global functions
|
30
28
|
*/
|
31
29
|
|
30
|
+
/*
|
31
|
+
* Convenience function to raise connection errors
|
32
|
+
*/
|
33
|
+
#ifdef __GNUC__
|
34
|
+
__attribute__((format(printf, 3, 4)))
|
35
|
+
#endif
|
36
|
+
static void
|
37
|
+
pg_raise_conn_error( VALUE klass, VALUE self, const char *format, ...)
|
38
|
+
{
|
39
|
+
VALUE msg, error;
|
40
|
+
va_list ap;
|
41
|
+
|
42
|
+
va_start(ap, format);
|
43
|
+
msg = rb_vsprintf(format, ap);
|
44
|
+
va_end(ap);
|
45
|
+
error = rb_exc_new_str(klass, msg);
|
46
|
+
rb_iv_set(error, "@connection", self);
|
47
|
+
rb_exc_raise(error);
|
48
|
+
}
|
49
|
+
|
32
50
|
/*
|
33
51
|
* Fetch the PG::Connection object data pointer.
|
34
52
|
*/
|
@@ -52,7 +70,7 @@ pg_get_connection_safe( VALUE self )
|
|
52
70
|
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
53
71
|
|
54
72
|
if ( !this->pgconn )
|
55
|
-
|
73
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
56
74
|
|
57
75
|
return this;
|
58
76
|
}
|
@@ -70,8 +88,9 @@ pg_get_pgconn( VALUE self )
|
|
70
88
|
t_pg_connection *this;
|
71
89
|
TypedData_Get_Struct( self, t_pg_connection, &pg_connection_type, this);
|
72
90
|
|
73
|
-
if ( !this->pgconn )
|
74
|
-
|
91
|
+
if ( !this->pgconn ){
|
92
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "connection is closed");
|
93
|
+
}
|
75
94
|
|
76
95
|
return this->pgconn;
|
77
96
|
}
|
@@ -89,14 +108,13 @@ pgconn_close_socket_io( VALUE self )
|
|
89
108
|
|
90
109
|
if ( RTEST(socket_io) ) {
|
91
110
|
#if defined(_WIN32)
|
92
|
-
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
93
|
-
|
94
|
-
}
|
111
|
+
if( rb_w32_unwrap_io_handle(this->ruby_sd) )
|
112
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not unwrap win32 socket handle");
|
95
113
|
#endif
|
96
114
|
rb_funcall( socket_io, rb_intern("close"), 0 );
|
97
115
|
}
|
98
116
|
|
99
|
-
this->socket_io
|
117
|
+
RB_OBJ_WRITE(self, &this->socket_io, Qnil);
|
100
118
|
}
|
101
119
|
|
102
120
|
|
@@ -216,7 +234,7 @@ static const rb_data_type_t pg_connection_type = {
|
|
216
234
|
},
|
217
235
|
0,
|
218
236
|
0,
|
219
|
-
|
237
|
+
RUBY_TYPED_WB_PROTECTED,
|
220
238
|
};
|
221
239
|
|
222
240
|
|
@@ -237,14 +255,15 @@ pgconn_s_allocate( VALUE klass )
|
|
237
255
|
VALUE self = TypedData_Make_Struct( klass, t_pg_connection, &pg_connection_type, this );
|
238
256
|
|
239
257
|
this->pgconn = NULL;
|
240
|
-
this->socket_io
|
241
|
-
this->notice_receiver
|
242
|
-
this->notice_processor
|
243
|
-
this->type_map_for_queries
|
244
|
-
this->type_map_for_results
|
245
|
-
this->encoder_for_put_copy_data
|
246
|
-
this->decoder_for_get_copy_data
|
247
|
-
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));
|
248
267
|
|
249
268
|
return self;
|
250
269
|
}
|
@@ -254,7 +273,6 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
254
273
|
{
|
255
274
|
t_pg_connection *this;
|
256
275
|
VALUE conninfo;
|
257
|
-
VALUE error;
|
258
276
|
VALUE self = pgconn_s_allocate( klass );
|
259
277
|
|
260
278
|
this = pg_get_connection( self );
|
@@ -262,13 +280,10 @@ pgconn_s_sync_connect(int argc, VALUE *argv, VALUE klass)
|
|
262
280
|
this->pgconn = gvl_PQconnectdb(StringValueCStr(conninfo));
|
263
281
|
|
264
282
|
if(this->pgconn == NULL)
|
265
|
-
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate structure");
|
283
|
+
rb_raise(rb_ePGerror, "PQconnectdb() unable to allocate PGconn structure");
|
266
284
|
|
267
|
-
if (PQstatus(this->pgconn) == CONNECTION_BAD)
|
268
|
-
|
269
|
-
rb_iv_set(error, "@connection", self);
|
270
|
-
rb_exc_raise(error);
|
271
|
-
}
|
285
|
+
if (PQstatus(this->pgconn) == CONNECTION_BAD)
|
286
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(this->pgconn));
|
272
287
|
|
273
288
|
pgconn_set_default_encoding( self );
|
274
289
|
|
@@ -301,7 +316,6 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
301
316
|
{
|
302
317
|
VALUE rb_conn;
|
303
318
|
VALUE conninfo;
|
304
|
-
VALUE error;
|
305
319
|
t_pg_connection *this;
|
306
320
|
|
307
321
|
/*
|
@@ -314,13 +328,10 @@ pgconn_s_connect_start( int argc, VALUE *argv, VALUE klass )
|
|
314
328
|
this->pgconn = gvl_PQconnectStart( StringValueCStr(conninfo) );
|
315
329
|
|
316
330
|
if( this->pgconn == NULL )
|
317
|
-
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate structure");
|
331
|
+
rb_raise(rb_ePGerror, "PQconnectStart() unable to allocate PGconn structure");
|
318
332
|
|
319
|
-
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
320
|
-
|
321
|
-
rb_iv_set(error, "@connection", rb_conn);
|
322
|
-
rb_exc_raise(error);
|
323
|
-
}
|
333
|
+
if ( PQstatus(this->pgconn) == CONNECTION_BAD )
|
334
|
+
pg_raise_conn_error( rb_eConnectionBad, rb_conn, "%s", PQerrorMessage(this->pgconn));
|
324
335
|
|
325
336
|
if ( rb_block_given_p() ) {
|
326
337
|
return rb_ensure( rb_yield, rb_conn, pgconn_finish, rb_conn );
|
@@ -376,6 +387,36 @@ pgconn_s_conndefaults(VALUE self)
|
|
376
387
|
return array;
|
377
388
|
}
|
378
389
|
|
390
|
+
/*
|
391
|
+
* Document-method: PG::Connection.conninfo_parse
|
392
|
+
*
|
393
|
+
* call-seq:
|
394
|
+
* PG::Connection.conninfo_parse(conninfo_string) -> Array
|
395
|
+
*
|
396
|
+
* Returns parsed connection options from the provided connection string as an array of hashes.
|
397
|
+
* Each hash has the same keys as PG::Connection.conndefaults() .
|
398
|
+
* The values from the +conninfo_string+ are stored in the +:val+ key.
|
399
|
+
*/
|
400
|
+
static VALUE
|
401
|
+
pgconn_s_conninfo_parse(VALUE self, VALUE conninfo)
|
402
|
+
{
|
403
|
+
VALUE array;
|
404
|
+
char *errmsg = NULL;
|
405
|
+
PQconninfoOption *options = PQconninfoParse(StringValueCStr(conninfo), &errmsg);
|
406
|
+
if(errmsg){
|
407
|
+
VALUE error = rb_str_new_cstr(errmsg);
|
408
|
+
PQfreemem(errmsg);
|
409
|
+
rb_raise(rb_ePGerror, "%"PRIsVALUE, error);
|
410
|
+
}
|
411
|
+
array = pgconn_make_conninfo_array( options );
|
412
|
+
|
413
|
+
PQconninfoFree(options);
|
414
|
+
|
415
|
+
UNUSED( self );
|
416
|
+
|
417
|
+
return array;
|
418
|
+
}
|
419
|
+
|
379
420
|
|
380
421
|
#ifdef HAVE_PQENCRYPTPASSWORDCONN
|
381
422
|
static VALUE
|
@@ -396,7 +437,7 @@ pgconn_sync_encrypt_password(int argc, VALUE *argv, VALUE self)
|
|
396
437
|
rval = rb_str_new2( encrypted );
|
397
438
|
PQfreemem( encrypted );
|
398
439
|
} else {
|
399
|
-
|
440
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
400
441
|
}
|
401
442
|
|
402
443
|
return rval;
|
@@ -450,17 +491,18 @@ pgconn_s_encrypt_password(VALUE self, VALUE password, VALUE username)
|
|
450
491
|
* the asynchronous connection is ready
|
451
492
|
*
|
452
493
|
* Example:
|
453
|
-
*
|
454
|
-
*
|
494
|
+
* require "io/wait"
|
495
|
+
*
|
496
|
+
* conn = PG::Connection.connect_start(dbname: 'mydatabase')
|
455
497
|
* status = conn.connect_poll
|
456
498
|
* while(status != PG::PGRES_POLLING_OK) do
|
457
499
|
* # do some work while waiting for the connection to complete
|
458
500
|
* if(status == PG::PGRES_POLLING_READING)
|
459
|
-
*
|
501
|
+
* unless conn.socket_io.wait_readable(10.0)
|
460
502
|
* raise "Asynchronous connection timed out!"
|
461
503
|
* end
|
462
504
|
* elsif(status == PG::PGRES_POLLING_WRITING)
|
463
|
-
*
|
505
|
+
* unless conn.socket_io.wait_writable(10.0)
|
464
506
|
* raise "Asynchronous connection timed out!"
|
465
507
|
* end
|
466
508
|
* end
|
@@ -536,7 +578,7 @@ pgconn_reset_start(VALUE self)
|
|
536
578
|
{
|
537
579
|
pgconn_close_socket_io( self );
|
538
580
|
if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
|
539
|
-
|
581
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
|
540
582
|
return Qnil;
|
541
583
|
}
|
542
584
|
|
@@ -606,7 +648,18 @@ pgconn_pass(VALUE self)
|
|
606
648
|
* call-seq:
|
607
649
|
* conn.host()
|
608
650
|
*
|
609
|
-
* Returns the
|
651
|
+
* Returns the server host name of the active connection.
|
652
|
+
* This can be a host name, an IP address, or a directory path if the connection is via Unix socket.
|
653
|
+
* (The path case can be distinguished because it will always be an absolute path, beginning with +/+ .)
|
654
|
+
*
|
655
|
+
* If the connection parameters specified both host and hostaddr, then +host+ will return the host information.
|
656
|
+
* If only hostaddr was specified, then that is returned.
|
657
|
+
* If multiple hosts were specified in the connection parameters, +host+ returns the host actually connected to.
|
658
|
+
*
|
659
|
+
* If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
|
660
|
+
*
|
661
|
+
* If multiple hosts were specified in the connection parameters, it is not possible to rely on the result of +host+ until the connection is established.
|
662
|
+
* The status of the connection can be checked using the function Connection#status .
|
610
663
|
*/
|
611
664
|
static VALUE
|
612
665
|
pgconn_host(VALUE self)
|
@@ -616,6 +669,26 @@ pgconn_host(VALUE self)
|
|
616
669
|
return rb_str_new2(host);
|
617
670
|
}
|
618
671
|
|
672
|
+
/* PQhostaddr() appeared in PostgreSQL-12 together with PQresultMemorySize() */
|
673
|
+
#if defined(HAVE_PQRESULTMEMORYSIZE)
|
674
|
+
/*
|
675
|
+
* call-seq:
|
676
|
+
* conn.hostaddr()
|
677
|
+
*
|
678
|
+
* Returns the server IP address of the active connection.
|
679
|
+
* This can be the address that a host name resolved to, or an IP address provided through the hostaddr parameter.
|
680
|
+
* If there is an error producing the host information (perhaps if the connection has not been fully established or there was an error), it returns an empty string.
|
681
|
+
*
|
682
|
+
*/
|
683
|
+
static VALUE
|
684
|
+
pgconn_hostaddr(VALUE self)
|
685
|
+
{
|
686
|
+
char *host = PQhostaddr(pg_get_pgconn(self));
|
687
|
+
if (!host) return Qnil;
|
688
|
+
return rb_str_new2(host);
|
689
|
+
}
|
690
|
+
#endif
|
691
|
+
|
619
692
|
/*
|
620
693
|
* call-seq:
|
621
694
|
* conn.port()
|
@@ -626,7 +699,10 @@ static VALUE
|
|
626
699
|
pgconn_port(VALUE self)
|
627
700
|
{
|
628
701
|
char* port = PQport(pg_get_pgconn(self));
|
629
|
-
|
702
|
+
if (!port || port[0] == '\0')
|
703
|
+
return INT2NUM(DEF_PGPORT);
|
704
|
+
else
|
705
|
+
return INT2NUM(atoi(port));
|
630
706
|
}
|
631
707
|
|
632
708
|
/*
|
@@ -686,6 +762,13 @@ pgconn_conninfo( VALUE self )
|
|
686
762
|
* PG::Constants::CONNECTION_BAD
|
687
763
|
*
|
688
764
|
* ... and other constants of kind PG::Constants::CONNECTION_*
|
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
|
+
*
|
770
|
+
* Example:
|
771
|
+
* PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == conn.status} # => :CONNECTION_OK
|
689
772
|
*/
|
690
773
|
static VALUE
|
691
774
|
pgconn_status(VALUE self)
|
@@ -810,7 +893,8 @@ pgconn_socket(VALUE self)
|
|
810
893
|
pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
|
811
894
|
|
812
895
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
813
|
-
|
896
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
897
|
+
|
814
898
|
return INT2NUM(sd);
|
815
899
|
}
|
816
900
|
|
@@ -818,13 +902,15 @@ pgconn_socket(VALUE self)
|
|
818
902
|
* call-seq:
|
819
903
|
* conn.socket_io() -> IO
|
820
904
|
*
|
821
|
-
* Fetch
|
822
|
-
* This object can be used for IO.select to wait for events while running
|
823
|
-
*
|
905
|
+
* Fetch an IO object created from the Connection's underlying socket.
|
906
|
+
* This object can be used per <tt>socket_io.wait_readable</tt>, <tt>socket_io.wait_writable</tt> or for <tt>IO.select</tt> to wait for events while running asynchronous API calls.
|
907
|
+
* <tt>IO#wait_*able</tt> is is <tt>Fiber.scheduler</tt> compatible in contrast to <tt>IO.select</tt>.
|
908
|
+
*
|
909
|
+
* The IO object can change while the connection is established, but is memorized afterwards.
|
910
|
+
* So be sure not to cache the IO object, but repeat calling <tt>conn.socket_io</tt> instead.
|
824
911
|
*
|
825
|
-
* Using this
|
826
|
-
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
827
|
-
* goes out of scope. In contrast to #socket, it also works on Windows.
|
912
|
+
* Using this method also works on Windows in contrast to using #socket .
|
913
|
+
* It also avoids the problem of the underlying connection being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt> goes out of scope.
|
828
914
|
*/
|
829
915
|
static VALUE
|
830
916
|
pgconn_socket_io(VALUE self)
|
@@ -836,14 +922,15 @@ pgconn_socket_io(VALUE self)
|
|
836
922
|
VALUE socket_io = this->socket_io;
|
837
923
|
|
838
924
|
if ( !RTEST(socket_io) ) {
|
839
|
-
if( (sd = PQsocket(this->pgconn)) < 0)
|
840
|
-
|
925
|
+
if( (sd = PQsocket(this->pgconn)) < 0){
|
926
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
927
|
+
}
|
841
928
|
|
842
929
|
#ifdef _WIN32
|
843
930
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
844
|
-
if( ruby_sd == -1 )
|
845
|
-
|
846
|
-
|
931
|
+
if( ruby_sd == -1 )
|
932
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
933
|
+
|
847
934
|
this->ruby_sd = ruby_sd;
|
848
935
|
#else
|
849
936
|
ruby_sd = sd;
|
@@ -855,7 +942,7 @@ pgconn_socket_io(VALUE self)
|
|
855
942
|
/* Disable autoclose feature */
|
856
943
|
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
857
944
|
|
858
|
-
this->socket_io
|
945
|
+
RB_OBJ_WRITE(self, &this->socket_io, socket_io);
|
859
946
|
}
|
860
947
|
|
861
948
|
return socket_io;
|
@@ -908,7 +995,7 @@ pgconn_backend_key(VALUE self)
|
|
908
995
|
|
909
996
|
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
910
997
|
if(cancel == NULL)
|
911
|
-
|
998
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
912
999
|
|
913
1000
|
if( cancel->be_pid != PQbackendPID(conn) )
|
914
1001
|
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
@@ -1072,7 +1159,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1072
1159
|
},
|
1073
1160
|
0,
|
1074
1161
|
0,
|
1075
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1162
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1076
1163
|
};
|
1077
1164
|
|
1078
1165
|
static char *
|
@@ -1105,7 +1192,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1105
1192
|
},
|
1106
1193
|
0,
|
1107
1194
|
0,
|
1108
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1195
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1109
1196
|
};
|
1110
1197
|
|
1111
1198
|
static int
|
@@ -1444,8 +1531,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1444
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.
|
1445
1532
|
*/
|
1446
1533
|
static VALUE
|
1447
|
-
pgconn_sync_describe_portal(self, stmt_name)
|
1448
|
-
VALUE self, stmt_name;
|
1534
|
+
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
1449
1535
|
{
|
1450
1536
|
PGresult *result;
|
1451
1537
|
VALUE rb_pgresult;
|
@@ -1537,9 +1623,9 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1537
1623
|
if( !singleton ) {
|
1538
1624
|
size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
|
1539
1625
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1540
|
-
if(error)
|
1541
|
-
|
1542
|
-
|
1626
|
+
if(error)
|
1627
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
|
1628
|
+
|
1543
1629
|
} else {
|
1544
1630
|
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
1545
1631
|
}
|
@@ -1635,7 +1721,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1635
1721
|
{
|
1636
1722
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1637
1723
|
char *escaped = NULL;
|
1638
|
-
VALUE error;
|
1639
1724
|
VALUE result = Qnil;
|
1640
1725
|
int enc_idx = this->enc_idx;
|
1641
1726
|
|
@@ -1646,12 +1731,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1646
1731
|
|
1647
1732
|
escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1648
1733
|
if (escaped == NULL)
|
1649
|
-
|
1650
|
-
|
1651
|
-
rb_iv_set(error, "@connection", self);
|
1652
|
-
rb_exc_raise(error);
|
1653
|
-
return Qnil;
|
1654
|
-
}
|
1734
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
1735
|
+
|
1655
1736
|
result = rb_str_new2(escaped);
|
1656
1737
|
PQfreemem(escaped);
|
1657
1738
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
@@ -1674,7 +1755,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1674
1755
|
{
|
1675
1756
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1676
1757
|
char *escaped = NULL;
|
1677
|
-
VALUE error;
|
1678
1758
|
VALUE result = Qnil;
|
1679
1759
|
int enc_idx = this->enc_idx;
|
1680
1760
|
|
@@ -1685,12 +1765,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1685
1765
|
|
1686
1766
|
escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1687
1767
|
if (escaped == NULL)
|
1688
|
-
|
1689
|
-
|
1690
|
-
rb_iv_set(error, "@connection", self);
|
1691
|
-
rb_exc_raise(error);
|
1692
|
-
return Qnil;
|
1693
|
-
}
|
1768
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
1769
|
+
|
1694
1770
|
result = rb_str_new2(escaped);
|
1695
1771
|
PQfreemem(escaped);
|
1696
1772
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
@@ -1738,14 +1814,10 @@ static VALUE
|
|
1738
1814
|
pgconn_set_single_row_mode(VALUE self)
|
1739
1815
|
{
|
1740
1816
|
PGconn *conn = pg_get_pgconn(self);
|
1741
|
-
VALUE error;
|
1742
1817
|
|
1818
|
+
rb_check_frozen(self);
|
1743
1819
|
if( PQsetSingleRowMode(conn) == 0 )
|
1744
|
-
|
1745
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
1746
|
-
rb_iv_set(error, "@connection", self);
|
1747
|
-
rb_exc_raise(error);
|
1748
|
-
}
|
1820
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
1749
1821
|
|
1750
1822
|
return self;
|
1751
1823
|
}
|
@@ -1769,15 +1841,12 @@ static VALUE
|
|
1769
1841
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1770
1842
|
{
|
1771
1843
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1772
|
-
VALUE error;
|
1773
1844
|
|
1774
1845
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
1775
1846
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1776
|
-
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
1777
|
-
|
1778
|
-
|
1779
|
-
rb_exc_raise(error);
|
1780
|
-
}
|
1847
|
+
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
1848
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1849
|
+
|
1781
1850
|
pgconn_wait_for_flush( self );
|
1782
1851
|
return Qnil;
|
1783
1852
|
}
|
@@ -1834,7 +1903,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1834
1903
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1835
1904
|
int result;
|
1836
1905
|
VALUE command, in_res_fmt;
|
1837
|
-
VALUE error;
|
1838
1906
|
int nParams;
|
1839
1907
|
int resultFormat;
|
1840
1908
|
struct query_params_data paramsData = { this->enc_idx };
|
@@ -1851,11 +1919,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1851
1919
|
|
1852
1920
|
free_query_params( ¶msData );
|
1853
1921
|
|
1854
|
-
if(result == 0)
|
1855
|
-
|
1856
|
-
|
1857
|
-
rb_exc_raise(error);
|
1858
|
-
}
|
1922
|
+
if(result == 0)
|
1923
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1924
|
+
|
1859
1925
|
pgconn_wait_for_flush( self );
|
1860
1926
|
return Qnil;
|
1861
1927
|
}
|
@@ -1887,7 +1953,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1887
1953
|
int result;
|
1888
1954
|
VALUE name, command, in_paramtypes;
|
1889
1955
|
VALUE param;
|
1890
|
-
VALUE error;
|
1891
1956
|
int i = 0;
|
1892
1957
|
int nParams = 0;
|
1893
1958
|
Oid *paramTypes = NULL;
|
@@ -1916,9 +1981,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1916
1981
|
xfree(paramTypes);
|
1917
1982
|
|
1918
1983
|
if(result == 0) {
|
1919
|
-
|
1920
|
-
rb_iv_set(error, "@connection", self);
|
1921
|
-
rb_exc_raise(error);
|
1984
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1922
1985
|
}
|
1923
1986
|
pgconn_wait_for_flush( self );
|
1924
1987
|
return Qnil;
|
@@ -1962,7 +2025,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1962
2025
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1963
2026
|
int result;
|
1964
2027
|
VALUE name, in_res_fmt;
|
1965
|
-
VALUE error;
|
1966
2028
|
int nParams;
|
1967
2029
|
int resultFormat;
|
1968
2030
|
struct query_params_data paramsData = { this->enc_idx };
|
@@ -1984,11 +2046,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1984
2046
|
|
1985
2047
|
free_query_params( ¶msData );
|
1986
2048
|
|
1987
|
-
if(result == 0)
|
1988
|
-
|
1989
|
-
|
1990
|
-
rb_exc_raise(error);
|
1991
|
-
}
|
2049
|
+
if(result == 0)
|
2050
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2051
|
+
|
1992
2052
|
pgconn_wait_for_flush( self );
|
1993
2053
|
return Qnil;
|
1994
2054
|
}
|
@@ -2003,14 +2063,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
2003
2063
|
static VALUE
|
2004
2064
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
2005
2065
|
{
|
2006
|
-
VALUE error;
|
2007
2066
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2008
2067
|
/* returns 0 on failure */
|
2009
|
-
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
2010
|
-
|
2011
|
-
|
2012
|
-
rb_exc_raise(error);
|
2013
|
-
}
|
2068
|
+
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
2069
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2070
|
+
|
2014
2071
|
pgconn_wait_for_flush( self );
|
2015
2072
|
return Qnil;
|
2016
2073
|
}
|
@@ -2026,14 +2083,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2026
2083
|
static VALUE
|
2027
2084
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
2028
2085
|
{
|
2029
|
-
VALUE error;
|
2030
2086
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2031
2087
|
/* returns 0 on failure */
|
2032
|
-
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
2033
|
-
|
2034
|
-
|
2035
|
-
rb_exc_raise(error);
|
2036
|
-
}
|
2088
|
+
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
2089
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2090
|
+
|
2037
2091
|
pgconn_wait_for_flush( self );
|
2038
2092
|
return Qnil;
|
2039
2093
|
}
|
@@ -2066,18 +2120,15 @@ pgconn_sync_get_result(VALUE self)
|
|
2066
2120
|
* or *notifies* to see if the state has changed.
|
2067
2121
|
*/
|
2068
2122
|
static VALUE
|
2069
|
-
pgconn_consume_input(self)
|
2070
|
-
VALUE self;
|
2123
|
+
pgconn_consume_input(VALUE self)
|
2071
2124
|
{
|
2072
|
-
VALUE error;
|
2073
2125
|
PGconn *conn = pg_get_pgconn(self);
|
2074
2126
|
/* returns 0 on error */
|
2075
2127
|
if(PQconsumeInput(conn) == 0) {
|
2076
2128
|
pgconn_close_socket_io(self);
|
2077
|
-
|
2078
|
-
rb_iv_set(error, "@connection", self);
|
2079
|
-
rb_exc_raise(error);
|
2129
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
|
2080
2130
|
}
|
2131
|
+
|
2081
2132
|
return Qnil;
|
2082
2133
|
}
|
2083
2134
|
|
@@ -2089,19 +2140,17 @@ pgconn_consume_input(self)
|
|
2089
2140
|
* #get_result would block. Otherwise returns +false+.
|
2090
2141
|
*/
|
2091
2142
|
static VALUE
|
2092
|
-
pgconn_is_busy(self)
|
2093
|
-
VALUE self;
|
2143
|
+
pgconn_is_busy(VALUE self)
|
2094
2144
|
{
|
2095
2145
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2096
2146
|
}
|
2097
2147
|
|
2098
2148
|
static VALUE
|
2099
|
-
pgconn_sync_setnonblocking(self, state)
|
2100
|
-
VALUE self, state;
|
2149
|
+
pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
2101
2150
|
{
|
2102
2151
|
int arg;
|
2103
|
-
VALUE error;
|
2104
2152
|
PGconn *conn = pg_get_pgconn(self);
|
2153
|
+
rb_check_frozen(self);
|
2105
2154
|
if(state == Qtrue)
|
2106
2155
|
arg = 1;
|
2107
2156
|
else if (state == Qfalse)
|
@@ -2109,18 +2158,15 @@ pgconn_sync_setnonblocking(self, state)
|
|
2109
2158
|
else
|
2110
2159
|
rb_raise(rb_eArgError, "Boolean value expected");
|
2111
2160
|
|
2112
|
-
if(PQsetnonblocking(conn, arg) == -1)
|
2113
|
-
|
2114
|
-
|
2115
|
-
rb_exc_raise(error);
|
2116
|
-
}
|
2161
|
+
if(PQsetnonblocking(conn, arg) == -1)
|
2162
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
2163
|
+
|
2117
2164
|
return Qnil;
|
2118
2165
|
}
|
2119
2166
|
|
2120
2167
|
|
2121
2168
|
static VALUE
|
2122
|
-
pgconn_sync_isnonblocking(self)
|
2123
|
-
VALUE self;
|
2169
|
+
pgconn_sync_isnonblocking(VALUE self)
|
2124
2170
|
{
|
2125
2171
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2126
2172
|
}
|
@@ -2129,14 +2175,10 @@ static VALUE
|
|
2129
2175
|
pgconn_sync_flush(VALUE self)
|
2130
2176
|
{
|
2131
2177
|
PGconn *conn = pg_get_pgconn(self);
|
2132
|
-
int ret;
|
2133
|
-
|
2134
|
-
|
2135
|
-
|
2136
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
2137
|
-
rb_iv_set(error, "@connection", self);
|
2138
|
-
rb_exc_raise(error);
|
2139
|
-
}
|
2178
|
+
int ret = PQflush(conn);
|
2179
|
+
if(ret == -1)
|
2180
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
2181
|
+
|
2140
2182
|
return (ret) ? Qfalse : Qtrue;
|
2141
2183
|
}
|
2142
2184
|
|
@@ -2150,7 +2192,7 @@ pgconn_sync_cancel(VALUE self)
|
|
2150
2192
|
|
2151
2193
|
cancel = PQgetCancel(pg_get_pgconn(self));
|
2152
2194
|
if(cancel == NULL)
|
2153
|
-
|
2195
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
2154
2196
|
|
2155
2197
|
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
2156
2198
|
if(ret == 1)
|
@@ -2359,7 +2401,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
2359
2401
|
|
2360
2402
|
/* Is the given timeout valid? */
|
2361
2403
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
2362
|
-
VALUE socket_io
|
2404
|
+
VALUE socket_io;
|
2405
|
+
|
2406
|
+
/* before we wait for data, make sure everything has been sent */
|
2407
|
+
pgconn_async_flush(self);
|
2408
|
+
if ((retval=is_readable(conn)))
|
2409
|
+
return retval;
|
2410
|
+
|
2411
|
+
socket_io = pgconn_socket_io(self);
|
2363
2412
|
/* Wait for the socket to become readable before checking again */
|
2364
2413
|
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
2365
2414
|
} else {
|
@@ -2374,7 +2423,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
2374
2423
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2375
2424
|
if ( PQconsumeInput(conn) == 0 ){
|
2376
2425
|
pgconn_close_socket_io(self);
|
2377
|
-
|
2426
|
+
pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
|
2378
2427
|
}
|
2379
2428
|
}
|
2380
2429
|
|
@@ -2387,8 +2436,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
2387
2436
|
*
|
2388
2437
|
* Attempts to flush any queued output data to the server.
|
2389
2438
|
* Returns +true+ if data is successfully flushed, +false+
|
2390
|
-
* if not
|
2391
|
-
* nonblocking.
|
2439
|
+
* if not. It can only return +false+ if connection is
|
2440
|
+
* in nonblocking mode.
|
2392
2441
|
* Raises PG::Error if some other failure occurred.
|
2393
2442
|
*/
|
2394
2443
|
static VALUE
|
@@ -2400,8 +2449,9 @@ pgconn_async_flush(VALUE self)
|
|
2400
2449
|
VALUE socket_io = pgconn_socket_io(self);
|
2401
2450
|
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
2402
2451
|
|
2403
|
-
if (events & PG_RUBY_IO_READABLE)
|
2452
|
+
if (events & PG_RUBY_IO_READABLE){
|
2404
2453
|
pgconn_consume_input(self);
|
2454
|
+
}
|
2405
2455
|
}
|
2406
2456
|
return Qtrue;
|
2407
2457
|
}
|
@@ -2417,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
|
|
2417
2467
|
static VALUE
|
2418
2468
|
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2419
2469
|
t_pg_connection *conn = pg_get_connection(self);
|
2470
|
+
rb_check_frozen(self);
|
2420
2471
|
conn->flush_data = RTEST(enabled);
|
2421
2472
|
return enabled;
|
2422
2473
|
}
|
@@ -2524,11 +2575,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2524
2575
|
Check_Type(buffer, T_STRING);
|
2525
2576
|
|
2526
2577
|
ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
|
2527
|
-
if(ret == -1)
|
2528
|
-
|
2529
|
-
|
2530
|
-
rb_exc_raise(error);
|
2531
|
-
}
|
2578
|
+
if(ret == -1)
|
2579
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2580
|
+
|
2532
2581
|
RB_GC_GUARD(intermediate);
|
2533
2582
|
RB_GC_GUARD(buffer);
|
2534
2583
|
|
@@ -2539,7 +2588,6 @@ static VALUE
|
|
2539
2588
|
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2540
2589
|
{
|
2541
2590
|
VALUE str;
|
2542
|
-
VALUE error;
|
2543
2591
|
int ret;
|
2544
2592
|
const char *error_message = NULL;
|
2545
2593
|
t_pg_connection *this = pg_get_connection_safe( self );
|
@@ -2550,11 +2598,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2550
2598
|
error_message = pg_cstr_enc(str, this->enc_idx);
|
2551
2599
|
|
2552
2600
|
ret = gvl_PQputCopyEnd(this->pgconn, error_message);
|
2553
|
-
if(ret == -1)
|
2554
|
-
|
2555
|
-
|
2556
|
-
rb_exc_raise(error);
|
2557
|
-
}
|
2601
|
+
if(ret == -1)
|
2602
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2603
|
+
|
2558
2604
|
return (ret) ? Qtrue : Qfalse;
|
2559
2605
|
}
|
2560
2606
|
|
@@ -2562,7 +2608,6 @@ static VALUE
|
|
2562
2608
|
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2563
2609
|
{
|
2564
2610
|
VALUE async_in;
|
2565
|
-
VALUE error;
|
2566
2611
|
VALUE result;
|
2567
2612
|
int ret;
|
2568
2613
|
char *buffer;
|
@@ -2582,10 +2627,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2582
2627
|
}
|
2583
2628
|
|
2584
2629
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
2585
|
-
if(ret == -2)
|
2586
|
-
|
2587
|
-
rb_iv_set(error, "@connection", self);
|
2588
|
-
rb_exc_raise(error);
|
2630
|
+
if(ret == -2){ /* error */
|
2631
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2589
2632
|
}
|
2590
2633
|
if(ret == -1) { /* No data left */
|
2591
2634
|
return Qnil;
|
@@ -2679,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2679
2722
|
VALUE new_file;
|
2680
2723
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2681
2724
|
|
2725
|
+
rb_check_frozen(self);
|
2682
2726
|
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2683
2727
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2684
2728
|
|
@@ -2700,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2700
2744
|
rb_raise(rb_eArgError, "stream is not writable");
|
2701
2745
|
|
2702
2746
|
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2703
|
-
this->trace_stream
|
2747
|
+
RB_OBJ_WRITE(self, &this->trace_stream, new_file);
|
2704
2748
|
|
2705
2749
|
PQtrace(this->pgconn, new_fp);
|
2706
2750
|
return Qnil;
|
@@ -2719,7 +2763,7 @@ pgconn_untrace(VALUE self)
|
|
2719
2763
|
|
2720
2764
|
PQuntrace(this->pgconn);
|
2721
2765
|
rb_funcall(this->trace_stream, rb_intern("close"), 0);
|
2722
|
-
this->trace_stream
|
2766
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
2723
2767
|
return Qnil;
|
2724
2768
|
}
|
2725
2769
|
|
@@ -2778,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2778
2822
|
VALUE proc, old_proc;
|
2779
2823
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2780
2824
|
|
2825
|
+
rb_check_frozen(self);
|
2781
2826
|
/* If default_notice_receiver is unset, assume that the current
|
2782
2827
|
* notice receiver is the default, and save it to a global variable.
|
2783
2828
|
* This should not be a problem because the default receiver is
|
2784
2829
|
* always the same, so won't vary among connections.
|
2785
2830
|
*/
|
2786
|
-
if(default_notice_receiver == NULL)
|
2787
|
-
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);
|
2788
2833
|
|
2789
2834
|
old_proc = this->notice_receiver;
|
2790
2835
|
if( rb_block_given_p() ) {
|
@@ -2793,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2793
2838
|
} else {
|
2794
2839
|
/* if no block is given, set back to default */
|
2795
2840
|
proc = Qnil;
|
2796
|
-
PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
|
2841
|
+
PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
|
2797
2842
|
}
|
2798
2843
|
|
2799
|
-
this->notice_receiver
|
2844
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, proc);
|
2800
2845
|
return old_proc;
|
2801
2846
|
}
|
2802
2847
|
|
@@ -2811,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2811
2856
|
VALUE self = (VALUE)arg;
|
2812
2857
|
t_pg_connection *this = pg_get_connection( self );
|
2813
2858
|
|
2814
|
-
if (this->
|
2859
|
+
if (this->notice_processor != Qnil) {
|
2815
2860
|
VALUE message_str = rb_str_new2(message);
|
2816
2861
|
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2817
|
-
rb_funcall(this->
|
2862
|
+
rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
|
2818
2863
|
}
|
2819
2864
|
return;
|
2820
2865
|
}
|
@@ -2838,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
|
|
2838
2883
|
VALUE proc, old_proc;
|
2839
2884
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2840
2885
|
|
2886
|
+
rb_check_frozen(self);
|
2841
2887
|
/* If default_notice_processor is unset, assume that the current
|
2842
2888
|
* notice processor is the default, and save it to a global variable.
|
2843
2889
|
* This should not be a problem because the default processor is
|
2844
2890
|
* always the same, so won't vary among connections.
|
2845
2891
|
*/
|
2846
|
-
if(default_notice_processor == NULL)
|
2847
|
-
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);
|
2848
2894
|
|
2849
|
-
old_proc = this->
|
2895
|
+
old_proc = this->notice_processor;
|
2850
2896
|
if( rb_block_given_p() ) {
|
2851
2897
|
proc = rb_block_proc();
|
2852
2898
|
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
|
2853
2899
|
} else {
|
2854
2900
|
/* if no block is given, set back to default */
|
2855
2901
|
proc = Qnil;
|
2856
|
-
PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
|
2902
|
+
PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
|
2857
2903
|
}
|
2858
2904
|
|
2859
|
-
this->
|
2905
|
+
RB_OBJ_WRITE(self, &this->notice_processor, proc);
|
2860
2906
|
return old_proc;
|
2861
2907
|
}
|
2862
2908
|
|
@@ -2888,11 +2934,12 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2888
2934
|
{
|
2889
2935
|
PGconn *conn = pg_get_pgconn( self );
|
2890
2936
|
|
2937
|
+
rb_check_frozen(self);
|
2891
2938
|
Check_Type(str, T_STRING);
|
2892
2939
|
|
2893
|
-
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
2894
|
-
|
2895
|
-
|
2940
|
+
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
2941
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
2942
|
+
|
2896
2943
|
pgconn_set_internal_encoding_index( self );
|
2897
2944
|
|
2898
2945
|
return Qnil;
|
@@ -3056,7 +3103,7 @@ pgconn_async_get_last_result(VALUE self)
|
|
3056
3103
|
VALUE rb_pgresult = Qnil;
|
3057
3104
|
PGresult *cur, *prev;
|
3058
3105
|
|
3059
|
-
|
3106
|
+
cur = prev = NULL;
|
3060
3107
|
for(;;) {
|
3061
3108
|
int status;
|
3062
3109
|
|
@@ -3088,8 +3135,14 @@ pgconn_async_get_last_result(VALUE self)
|
|
3088
3135
|
* conn.discard_results()
|
3089
3136
|
*
|
3090
3137
|
* Silently discard any prior query result that application didn't eat.
|
3091
|
-
* This is
|
3092
|
-
*
|
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
|
+
*
|
3093
3146
|
*/
|
3094
3147
|
static VALUE
|
3095
3148
|
pgconn_discard_results(VALUE self)
|
@@ -3097,8 +3150,12 @@ pgconn_discard_results(VALUE self)
|
|
3097
3150
|
PGconn *conn = pg_get_pgconn(self);
|
3098
3151
|
VALUE socket_io;
|
3099
3152
|
|
3100
|
-
|
3101
|
-
|
3153
|
+
switch( PQtransactionStatus(conn) ) {
|
3154
|
+
case PQTRANS_IDLE:
|
3155
|
+
case PQTRANS_INTRANS:
|
3156
|
+
case PQTRANS_INERROR:
|
3157
|
+
return Qnil;
|
3158
|
+
default:;
|
3102
3159
|
}
|
3103
3160
|
|
3104
3161
|
socket_io = pgconn_socket_io(self);
|
@@ -3111,10 +3168,21 @@ pgconn_discard_results(VALUE self)
|
|
3111
3168
|
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
3112
3169
|
*/
|
3113
3170
|
while( gvl_PQisBusy(conn) ){
|
3114
|
-
|
3115
|
-
|
3116
|
-
|
3117
|
-
|
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;
|
3118
3186
|
}
|
3119
3187
|
}
|
3120
3188
|
|
@@ -3124,7 +3192,9 @@ pgconn_discard_results(VALUE self)
|
|
3124
3192
|
status = PQresultStatus(cur);
|
3125
3193
|
PQclear(cur);
|
3126
3194
|
if (status == PGRES_COPY_IN){
|
3127
|
-
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
|
+
}
|
3128
3198
|
}
|
3129
3199
|
if (status == PGRES_COPY_OUT){
|
3130
3200
|
for(;;) {
|
@@ -3133,10 +3203,7 @@ pgconn_discard_results(VALUE self)
|
|
3133
3203
|
if( st == 0 ) {
|
3134
3204
|
/* would block -> wait for readable data */
|
3135
3205
|
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3136
|
-
if ( PQconsumeInput(conn) == 0 )
|
3137
|
-
pgconn_close_socket_io(self);
|
3138
|
-
return Qfalse;
|
3139
|
-
}
|
3206
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
3140
3207
|
} else if( st > 0 ) {
|
3141
3208
|
/* some data retrieved -> discard it */
|
3142
3209
|
PQfreemem(buffer);
|
@@ -3149,6 +3216,10 @@ pgconn_discard_results(VALUE self)
|
|
3149
3216
|
}
|
3150
3217
|
|
3151
3218
|
return Qtrue;
|
3219
|
+
|
3220
|
+
error:
|
3221
|
+
pgconn_close_socket_io(self);
|
3222
|
+
return Qfalse;
|
3152
3223
|
}
|
3153
3224
|
|
3154
3225
|
/*
|
@@ -3525,11 +3596,10 @@ pgconn_enter_pipeline_mode(VALUE self)
|
|
3525
3596
|
{
|
3526
3597
|
PGconn *conn = pg_get_pgconn(self);
|
3527
3598
|
int res = PQenterPipelineMode(conn);
|
3528
|
-
if( res
|
3529
|
-
|
3530
|
-
|
3531
|
-
|
3532
|
-
}
|
3599
|
+
if( res != 1 )
|
3600
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3601
|
+
|
3602
|
+
return Qnil;
|
3533
3603
|
}
|
3534
3604
|
|
3535
3605
|
/*
|
@@ -3548,11 +3618,10 @@ pgconn_exit_pipeline_mode(VALUE self)
|
|
3548
3618
|
{
|
3549
3619
|
PGconn *conn = pg_get_pgconn(self);
|
3550
3620
|
int res = PQexitPipelineMode(conn);
|
3551
|
-
if( res
|
3552
|
-
|
3553
|
-
|
3554
|
-
|
3555
|
-
}
|
3621
|
+
if( res != 1 )
|
3622
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3623
|
+
|
3624
|
+
return Qnil;
|
3556
3625
|
}
|
3557
3626
|
|
3558
3627
|
|
@@ -3572,11 +3641,10 @@ pgconn_pipeline_sync(VALUE self)
|
|
3572
3641
|
{
|
3573
3642
|
PGconn *conn = pg_get_pgconn(self);
|
3574
3643
|
int res = PQpipelineSync(conn);
|
3575
|
-
if( res
|
3576
|
-
|
3577
|
-
|
3578
|
-
|
3579
|
-
}
|
3644
|
+
if( res != 1 )
|
3645
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3646
|
+
|
3647
|
+
return Qnil;
|
3580
3648
|
}
|
3581
3649
|
|
3582
3650
|
/*
|
@@ -3596,11 +3664,10 @@ pgconn_send_flush_request(VALUE self)
|
|
3596
3664
|
{
|
3597
3665
|
PGconn *conn = pg_get_pgconn(self);
|
3598
3666
|
int res = PQsendFlushRequest(conn);
|
3599
|
-
if( res
|
3600
|
-
|
3601
|
-
|
3602
|
-
|
3603
|
-
}
|
3667
|
+
if( res != 1 )
|
3668
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3669
|
+
|
3670
|
+
return Qnil;
|
3604
3671
|
}
|
3605
3672
|
|
3606
3673
|
#endif
|
@@ -3609,6 +3676,14 @@ pgconn_send_flush_request(VALUE self)
|
|
3609
3676
|
* LARGE OBJECT SUPPORT
|
3610
3677
|
**************************************************************************/
|
3611
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
|
+
|
3612
3687
|
/*
|
3613
3688
|
* call-seq:
|
3614
3689
|
* conn.lo_creat( [mode] ) -> Integer
|
@@ -3629,9 +3704,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
3629
3704
|
else
|
3630
3705
|
mode = NUM2INT(nmode);
|
3631
3706
|
|
3632
|
-
|
3707
|
+
BLOCKING_BEGIN(conn)
|
3708
|
+
lo_oid = lo_creat(conn, mode);
|
3709
|
+
BLOCKING_END(conn)
|
3710
|
+
|
3633
3711
|
if (lo_oid == 0)
|
3634
|
-
|
3712
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
|
3635
3713
|
|
3636
3714
|
return UINT2NUM(lo_oid);
|
3637
3715
|
}
|
@@ -3652,7 +3730,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
|
3652
3730
|
|
3653
3731
|
ret = lo_create(conn, lo_oid);
|
3654
3732
|
if (ret == InvalidOid)
|
3655
|
-
|
3733
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
|
3656
3734
|
|
3657
3735
|
return UINT2NUM(ret);
|
3658
3736
|
}
|
@@ -3674,9 +3752,12 @@ pgconn_loimport(VALUE self, VALUE filename)
|
|
3674
3752
|
|
3675
3753
|
Check_Type(filename, T_STRING);
|
3676
3754
|
|
3677
|
-
|
3755
|
+
BLOCKING_BEGIN(conn)
|
3756
|
+
lo_oid = lo_import(conn, StringValueCStr(filename));
|
3757
|
+
BLOCKING_END(conn)
|
3758
|
+
|
3678
3759
|
if (lo_oid == 0) {
|
3679
|
-
|
3760
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3680
3761
|
}
|
3681
3762
|
return UINT2NUM(lo_oid);
|
3682
3763
|
}
|
@@ -3692,12 +3773,17 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
3692
3773
|
{
|
3693
3774
|
PGconn *conn = pg_get_pgconn(self);
|
3694
3775
|
Oid oid;
|
3776
|
+
int ret;
|
3695
3777
|
Check_Type(filename, T_STRING);
|
3696
3778
|
|
3697
3779
|
oid = NUM2UINT(lo_oid);
|
3698
3780
|
|
3699
|
-
|
3700
|
-
|
3781
|
+
BLOCKING_BEGIN(conn)
|
3782
|
+
ret = lo_export(conn, oid, StringValueCStr(filename));
|
3783
|
+
BLOCKING_END(conn)
|
3784
|
+
|
3785
|
+
if (ret < 0) {
|
3786
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3701
3787
|
}
|
3702
3788
|
return Qnil;
|
3703
3789
|
}
|
@@ -3727,8 +3813,12 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
3727
3813
|
else
|
3728
3814
|
mode = NUM2INT(nmode);
|
3729
3815
|
|
3730
|
-
|
3731
|
-
|
3816
|
+
BLOCKING_BEGIN(conn)
|
3817
|
+
fd = lo_open(conn, lo_oid, mode);
|
3818
|
+
BLOCKING_END(conn)
|
3819
|
+
|
3820
|
+
if(fd < 0) {
|
3821
|
+
pg_raise_conn_error( rb_ePGerror, self, "can't open large object: %s", PQerrorMessage(conn));
|
3732
3822
|
}
|
3733
3823
|
return INT2FIX(fd);
|
3734
3824
|
}
|
@@ -3750,11 +3840,15 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
3750
3840
|
Check_Type(buffer, T_STRING);
|
3751
3841
|
|
3752
3842
|
if( RSTRING_LEN(buffer) < 0) {
|
3753
|
-
|
3843
|
+
pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
|
3754
3844
|
}
|
3755
|
-
|
3756
|
-
|
3757
|
-
|
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) {
|
3851
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_write failed: %s", PQerrorMessage(conn));
|
3758
3852
|
}
|
3759
3853
|
|
3760
3854
|
return INT2FIX(n);
|
@@ -3777,16 +3871,17 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3777
3871
|
VALUE str;
|
3778
3872
|
char *buffer;
|
3779
3873
|
|
3780
|
-
|
3781
|
-
|
3782
|
-
rb_raise(rb_eNoMemError, "ALLOC failed!");
|
3874
|
+
if (len < 0)
|
3875
|
+
pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
|
3783
3876
|
|
3784
|
-
|
3785
|
-
|
3786
|
-
|
3877
|
+
buffer = ALLOC_N(char, len);
|
3878
|
+
|
3879
|
+
BLOCKING_BEGIN(conn)
|
3880
|
+
ret = lo_read(conn, lo_desc, buffer, len);
|
3881
|
+
BLOCKING_END(conn)
|
3787
3882
|
|
3788
|
-
if(
|
3789
|
-
|
3883
|
+
if(ret < 0)
|
3884
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
|
3790
3885
|
|
3791
3886
|
if(ret == 0) {
|
3792
3887
|
xfree(buffer);
|
@@ -3815,8 +3910,12 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
3815
3910
|
int lo_desc = NUM2INT(in_lo_desc);
|
3816
3911
|
int ret;
|
3817
3912
|
|
3818
|
-
|
3819
|
-
|
3913
|
+
BLOCKING_BEGIN(conn)
|
3914
|
+
ret = lo_lseek(conn, lo_desc, NUM2INT(offset), NUM2INT(whence));
|
3915
|
+
BLOCKING_END(conn)
|
3916
|
+
|
3917
|
+
if(ret < 0) {
|
3918
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_lseek failed");
|
3820
3919
|
}
|
3821
3920
|
|
3822
3921
|
return INT2FIX(ret);
|
@@ -3835,8 +3934,12 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
|
3835
3934
|
PGconn *conn = pg_get_pgconn(self);
|
3836
3935
|
int lo_desc = NUM2INT(in_lo_desc);
|
3837
3936
|
|
3838
|
-
|
3839
|
-
|
3937
|
+
BLOCKING_BEGIN(conn)
|
3938
|
+
position = lo_tell(conn, lo_desc);
|
3939
|
+
BLOCKING_END(conn)
|
3940
|
+
|
3941
|
+
if(position < 0)
|
3942
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_tell failed");
|
3840
3943
|
|
3841
3944
|
return INT2FIX(position);
|
3842
3945
|
}
|
@@ -3853,9 +3956,14 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3853
3956
|
PGconn *conn = pg_get_pgconn(self);
|
3854
3957
|
int lo_desc = NUM2INT(in_lo_desc);
|
3855
3958
|
size_t len = NUM2INT(in_len);
|
3959
|
+
int ret;
|
3856
3960
|
|
3857
|
-
|
3858
|
-
|
3961
|
+
BLOCKING_BEGIN(conn)
|
3962
|
+
ret = lo_truncate(conn,lo_desc,len);
|
3963
|
+
BLOCKING_END(conn)
|
3964
|
+
|
3965
|
+
if(ret < 0)
|
3966
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
|
3859
3967
|
|
3860
3968
|
return Qnil;
|
3861
3969
|
}
|
@@ -3871,9 +3979,14 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
|
3871
3979
|
{
|
3872
3980
|
PGconn *conn = pg_get_pgconn(self);
|
3873
3981
|
int lo_desc = NUM2INT(in_lo_desc);
|
3982
|
+
int ret;
|
3874
3983
|
|
3875
|
-
|
3876
|
-
|
3984
|
+
BLOCKING_BEGIN(conn)
|
3985
|
+
ret = lo_close(conn,lo_desc);
|
3986
|
+
BLOCKING_END(conn)
|
3987
|
+
|
3988
|
+
if(ret < 0)
|
3989
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
|
3877
3990
|
|
3878
3991
|
return Qnil;
|
3879
3992
|
}
|
@@ -3889,9 +4002,14 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3889
4002
|
{
|
3890
4003
|
PGconn *conn = pg_get_pgconn(self);
|
3891
4004
|
Oid oid = NUM2UINT(in_oid);
|
4005
|
+
int ret;
|
3892
4006
|
|
3893
|
-
|
3894
|
-
|
4007
|
+
BLOCKING_BEGIN(conn)
|
4008
|
+
ret = lo_unlink(conn,oid);
|
4009
|
+
BLOCKING_END(conn)
|
4010
|
+
|
4011
|
+
if(ret < 0)
|
4012
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_unlink failed");
|
3895
4013
|
|
3896
4014
|
return Qnil;
|
3897
4015
|
}
|
@@ -3948,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
3948
4066
|
static VALUE
|
3949
4067
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3950
4068
|
{
|
4069
|
+
rb_check_frozen(self);
|
3951
4070
|
if (NIL_P(enc)) {
|
3952
4071
|
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3953
4072
|
return enc;
|
@@ -4002,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4002
4121
|
{
|
4003
4122
|
VALUE query_format, query;
|
4004
4123
|
|
4124
|
+
rb_check_frozen(self);
|
4005
4125
|
Check_Type(encname, T_STRING);
|
4006
4126
|
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4007
4127
|
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
@@ -4054,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
|
|
4054
4174
|
rb_encoding *enc;
|
4055
4175
|
const char *encname;
|
4056
4176
|
|
4177
|
+
rb_check_frozen(self);
|
4057
4178
|
if (( enc = rb_default_internal_encoding() )) {
|
4058
4179
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
4059
4180
|
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
@@ -4083,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
4083
4204
|
t_typemap *tm;
|
4084
4205
|
UNUSED(tm);
|
4085
4206
|
|
4207
|
+
rb_check_frozen(self);
|
4086
4208
|
/* Check type of method param */
|
4087
4209
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4088
4210
|
|
4089
|
-
this->type_map_for_queries
|
4211
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
|
4090
4212
|
|
4091
4213
|
return typemap;
|
4092
4214
|
}
|
@@ -4123,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
4123
4245
|
t_typemap *tm;
|
4124
4246
|
UNUSED(tm);
|
4125
4247
|
|
4248
|
+
rb_check_frozen(self);
|
4126
4249
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4127
|
-
this->type_map_for_results
|
4250
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
|
4128
4251
|
|
4129
4252
|
return typemap;
|
4130
4253
|
}
|
@@ -4162,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4162
4285
|
{
|
4163
4286
|
t_pg_connection *this = pg_get_connection( self );
|
4164
4287
|
|
4288
|
+
rb_check_frozen(self);
|
4165
4289
|
if( encoder != Qnil ){
|
4166
4290
|
t_pg_coder *co;
|
4167
4291
|
UNUSED(co);
|
4168
4292
|
/* Check argument type */
|
4169
4293
|
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4170
4294
|
}
|
4171
|
-
this->encoder_for_put_copy_data
|
4295
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
|
4172
4296
|
|
4173
4297
|
return encoder;
|
4174
4298
|
}
|
@@ -4210,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4210
4334
|
{
|
4211
4335
|
t_pg_connection *this = pg_get_connection( self );
|
4212
4336
|
|
4337
|
+
rb_check_frozen(self);
|
4213
4338
|
if( decoder != Qnil ){
|
4214
4339
|
t_pg_coder *co;
|
4215
4340
|
UNUSED(co);
|
4216
4341
|
/* Check argument type */
|
4217
4342
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4218
4343
|
}
|
4219
|
-
this->decoder_for_get_copy_data
|
4344
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
|
4220
4345
|
|
4221
4346
|
return decoder;
|
4222
4347
|
}
|
@@ -4262,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
4262
4387
|
{
|
4263
4388
|
t_pg_connection *this = pg_get_connection( self );
|
4264
4389
|
|
4390
|
+
rb_check_frozen(self);
|
4265
4391
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4266
4392
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4267
4393
|
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
@@ -4298,7 +4424,7 @@ pgconn_field_name_type_get(VALUE self)
|
|
4298
4424
|
* Document-class: PG::Connection
|
4299
4425
|
*/
|
4300
4426
|
void
|
4301
|
-
init_pg_connection()
|
4427
|
+
init_pg_connection(void)
|
4302
4428
|
{
|
4303
4429
|
s_id_encode = rb_intern("encode");
|
4304
4430
|
s_id_autoclose_set = rb_intern("autoclose=");
|
@@ -4325,6 +4451,7 @@ init_pg_connection()
|
|
4325
4451
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4326
4452
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4327
4453
|
rb_define_singleton_method(rb_cPGconn, "conndefaults", pgconn_s_conndefaults, 0);
|
4454
|
+
rb_define_singleton_method(rb_cPGconn, "conninfo_parse", pgconn_s_conninfo_parse, 1);
|
4328
4455
|
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
4329
4456
|
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
4330
4457
|
|
@@ -4342,6 +4469,9 @@ init_pg_connection()
|
|
4342
4469
|
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
4343
4470
|
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
4344
4471
|
rb_define_method(rb_cPGconn, "host", pgconn_host, 0);
|
4472
|
+
#if defined(HAVE_PQRESULTMEMORYSIZE)
|
4473
|
+
rb_define_method(rb_cPGconn, "hostaddr", pgconn_hostaddr, 0);
|
4474
|
+
#endif
|
4345
4475
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
4346
4476
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
4347
4477
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|