pg 1.3.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} +302 -115
- 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.rb +0 -0
- data/ext/errorcodes.txt +2 -1
- data/ext/extconf.rb +0 -0
- data/ext/pg.c +14 -54
- data/ext/pg.h +12 -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 +385 -266
- 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 +117 -34
- data/ext/pg_text_decoder.c +28 -10
- data/ext/pg_text_encoder.c +23 -10
- data/ext/pg_tuple.c +36 -39
- 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 +269 -139
- 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/misc/openssl-pg-segfault.rb +0 -0
- data/pg.gemspec +4 -2
- data/rakelib/task_extension.rb +1 -1
- data/sample/array_insert.rb +0 -0
- data/sample/async_api.rb +3 -7
- data/sample/async_copyto.rb +0 -0
- data/sample/async_mixed.rb +0 -0
- data/sample/check_conn.rb +0 -0
- data/sample/copydata.rb +0 -0
- data/sample/copyfrom.rb +0 -0
- data/sample/copyto.rb +0 -0
- data/sample/cursor.rb +0 -0
- data/sample/disk_usage_report.rb +0 -0
- data/sample/issue-119.rb +0 -0
- data/sample/losample.rb +0 -0
- data/sample/minimal-testcase.rb +0 -0
- data/sample/notify_wait.rb +0 -0
- data/sample/pg_statistics.rb +0 -0
- data/sample/replication_monitor.rb +0 -0
- data/sample/test_binary_values.rb +0 -0
- data/sample/wal_shipper.rb +0 -0
- data/sample/warehouse_partitions.rb +0 -0
- 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
|
@@ -475,9 +517,7 @@ pgconn_connect_poll(VALUE self)
|
|
475
517
|
PostgresPollingStatusType status;
|
476
518
|
status = gvl_PQconnectPoll(pg_get_pgconn(self));
|
477
519
|
|
478
|
-
|
479
|
-
pgconn_close_socket_io(self);
|
480
|
-
}
|
520
|
+
pgconn_close_socket_io(self);
|
481
521
|
|
482
522
|
return INT2FIX((int)status);
|
483
523
|
}
|
@@ -538,7 +578,7 @@ pgconn_reset_start(VALUE self)
|
|
538
578
|
{
|
539
579
|
pgconn_close_socket_io( self );
|
540
580
|
if(gvl_PQresetStart(pg_get_pgconn(self)) == 0)
|
541
|
-
|
581
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "reset has failed");
|
542
582
|
return Qnil;
|
543
583
|
}
|
544
584
|
|
@@ -556,9 +596,7 @@ pgconn_reset_poll(VALUE self)
|
|
556
596
|
PostgresPollingStatusType status;
|
557
597
|
status = gvl_PQresetPoll(pg_get_pgconn(self));
|
558
598
|
|
559
|
-
|
560
|
-
pgconn_close_socket_io(self);
|
561
|
-
}
|
599
|
+
pgconn_close_socket_io(self);
|
562
600
|
|
563
601
|
return INT2FIX((int)status);
|
564
602
|
}
|
@@ -610,7 +648,18 @@ pgconn_pass(VALUE self)
|
|
610
648
|
* call-seq:
|
611
649
|
* conn.host()
|
612
650
|
*
|
613
|
-
* 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 .
|
614
663
|
*/
|
615
664
|
static VALUE
|
616
665
|
pgconn_host(VALUE self)
|
@@ -620,6 +669,26 @@ pgconn_host(VALUE self)
|
|
620
669
|
return rb_str_new2(host);
|
621
670
|
}
|
622
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
|
+
|
623
692
|
/*
|
624
693
|
* call-seq:
|
625
694
|
* conn.port()
|
@@ -630,7 +699,10 @@ static VALUE
|
|
630
699
|
pgconn_port(VALUE self)
|
631
700
|
{
|
632
701
|
char* port = PQport(pg_get_pgconn(self));
|
633
|
-
|
702
|
+
if (!port || port[0] == '\0')
|
703
|
+
return INT2NUM(DEF_PGPORT);
|
704
|
+
else
|
705
|
+
return INT2NUM(atoi(port));
|
634
706
|
}
|
635
707
|
|
636
708
|
/*
|
@@ -690,6 +762,13 @@ pgconn_conninfo( VALUE self )
|
|
690
762
|
* PG::Constants::CONNECTION_BAD
|
691
763
|
*
|
692
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
|
693
772
|
*/
|
694
773
|
static VALUE
|
695
774
|
pgconn_status(VALUE self)
|
@@ -814,7 +893,8 @@ pgconn_socket(VALUE self)
|
|
814
893
|
pg_deprecated(4, ("conn.socket is deprecated and should be replaced by conn.socket_io"));
|
815
894
|
|
816
895
|
if( (sd = PQsocket(pg_get_pgconn(self))) < 0)
|
817
|
-
|
896
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
897
|
+
|
818
898
|
return INT2NUM(sd);
|
819
899
|
}
|
820
900
|
|
@@ -822,13 +902,15 @@ pgconn_socket(VALUE self)
|
|
822
902
|
* call-seq:
|
823
903
|
* conn.socket_io() -> IO
|
824
904
|
*
|
825
|
-
* Fetch
|
826
|
-
* This object can be used for IO.select to wait for events while running
|
827
|
-
*
|
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.
|
828
911
|
*
|
829
|
-
* Using this
|
830
|
-
* being closed by Ruby when an IO created using <tt>IO.for_fd(conn.socket)</tt>
|
831
|
-
* 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.
|
832
914
|
*/
|
833
915
|
static VALUE
|
834
916
|
pgconn_socket_io(VALUE self)
|
@@ -840,14 +922,15 @@ pgconn_socket_io(VALUE self)
|
|
840
922
|
VALUE socket_io = this->socket_io;
|
841
923
|
|
842
924
|
if ( !RTEST(socket_io) ) {
|
843
|
-
if( (sd = PQsocket(this->pgconn)) < 0)
|
844
|
-
|
925
|
+
if( (sd = PQsocket(this->pgconn)) < 0){
|
926
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "PQsocket() can't get socket descriptor");
|
927
|
+
}
|
845
928
|
|
846
929
|
#ifdef _WIN32
|
847
930
|
ruby_sd = rb_w32_wrap_io_handle((HANDLE)(intptr_t)sd, O_RDWR|O_BINARY|O_NOINHERIT);
|
848
|
-
if( ruby_sd == -1 )
|
849
|
-
|
850
|
-
|
931
|
+
if( ruby_sd == -1 )
|
932
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "Could not wrap win32 socket handle");
|
933
|
+
|
851
934
|
this->ruby_sd = ruby_sd;
|
852
935
|
#else
|
853
936
|
ruby_sd = sd;
|
@@ -859,7 +942,7 @@ pgconn_socket_io(VALUE self)
|
|
859
942
|
/* Disable autoclose feature */
|
860
943
|
rb_funcall( socket_io, s_id_autoclose_set, 1, Qfalse );
|
861
944
|
|
862
|
-
this->socket_io
|
945
|
+
RB_OBJ_WRITE(self, &this->socket_io, socket_io);
|
863
946
|
}
|
864
947
|
|
865
948
|
return socket_io;
|
@@ -912,7 +995,7 @@ pgconn_backend_key(VALUE self)
|
|
912
995
|
|
913
996
|
cancel = (struct pg_cancel*)PQgetCancel(conn);
|
914
997
|
if(cancel == NULL)
|
915
|
-
|
998
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
916
999
|
|
917
1000
|
if( cancel->be_pid != PQbackendPID(conn) )
|
918
1001
|
rb_raise(rb_ePGerror,"Unexpected binary struct layout - please file a bug report at ruby-pg!");
|
@@ -1076,7 +1159,7 @@ static const rb_data_type_t pg_typecast_buffer_type = {
|
|
1076
1159
|
},
|
1077
1160
|
0,
|
1078
1161
|
0,
|
1079
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1162
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1080
1163
|
};
|
1081
1164
|
|
1082
1165
|
static char *
|
@@ -1109,7 +1192,7 @@ static const rb_data_type_t pg_query_heap_pool_type = {
|
|
1109
1192
|
},
|
1110
1193
|
0,
|
1111
1194
|
0,
|
1112
|
-
RUBY_TYPED_FREE_IMMEDIATELY,
|
1195
|
+
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED,
|
1113
1196
|
};
|
1114
1197
|
|
1115
1198
|
static int
|
@@ -1448,8 +1531,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
|
|
1448
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.
|
1449
1532
|
*/
|
1450
1533
|
static VALUE
|
1451
|
-
pgconn_sync_describe_portal(self, stmt_name)
|
1452
|
-
VALUE self, stmt_name;
|
1534
|
+
pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
|
1453
1535
|
{
|
1454
1536
|
PGresult *result;
|
1455
1537
|
VALUE rb_pgresult;
|
@@ -1541,9 +1623,9 @@ pgconn_s_escape(VALUE self, VALUE string)
|
|
1541
1623
|
if( !singleton ) {
|
1542
1624
|
size = PQescapeStringConn(pg_get_pgconn(self), RSTRING_PTR(result),
|
1543
1625
|
RSTRING_PTR(string), RSTRING_LEN(string), &error);
|
1544
|
-
if(error)
|
1545
|
-
|
1546
|
-
|
1626
|
+
if(error)
|
1627
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(pg_get_pgconn(self)));
|
1628
|
+
|
1547
1629
|
} else {
|
1548
1630
|
size = PQescapeString(RSTRING_PTR(result), RSTRING_PTR(string), RSTRING_LEN(string));
|
1549
1631
|
}
|
@@ -1639,7 +1721,6 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1639
1721
|
{
|
1640
1722
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1641
1723
|
char *escaped = NULL;
|
1642
|
-
VALUE error;
|
1643
1724
|
VALUE result = Qnil;
|
1644
1725
|
int enc_idx = this->enc_idx;
|
1645
1726
|
|
@@ -1650,12 +1731,8 @@ pgconn_escape_literal(VALUE self, VALUE string)
|
|
1650
1731
|
|
1651
1732
|
escaped = PQescapeLiteral(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1652
1733
|
if (escaped == NULL)
|
1653
|
-
|
1654
|
-
|
1655
|
-
rb_iv_set(error, "@connection", self);
|
1656
|
-
rb_exc_raise(error);
|
1657
|
-
return Qnil;
|
1658
|
-
}
|
1734
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
1735
|
+
|
1659
1736
|
result = rb_str_new2(escaped);
|
1660
1737
|
PQfreemem(escaped);
|
1661
1738
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
@@ -1678,7 +1755,6 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1678
1755
|
{
|
1679
1756
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1680
1757
|
char *escaped = NULL;
|
1681
|
-
VALUE error;
|
1682
1758
|
VALUE result = Qnil;
|
1683
1759
|
int enc_idx = this->enc_idx;
|
1684
1760
|
|
@@ -1689,12 +1765,8 @@ pgconn_escape_identifier(VALUE self, VALUE string)
|
|
1689
1765
|
|
1690
1766
|
escaped = PQescapeIdentifier(this->pgconn, RSTRING_PTR(string), RSTRING_LEN(string));
|
1691
1767
|
if (escaped == NULL)
|
1692
|
-
|
1693
|
-
|
1694
|
-
rb_iv_set(error, "@connection", self);
|
1695
|
-
rb_exc_raise(error);
|
1696
|
-
return Qnil;
|
1697
|
-
}
|
1768
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
1769
|
+
|
1698
1770
|
result = rb_str_new2(escaped);
|
1699
1771
|
PQfreemem(escaped);
|
1700
1772
|
PG_ENCODING_SET_NOCHECK(result, enc_idx);
|
@@ -1742,14 +1814,10 @@ static VALUE
|
|
1742
1814
|
pgconn_set_single_row_mode(VALUE self)
|
1743
1815
|
{
|
1744
1816
|
PGconn *conn = pg_get_pgconn(self);
|
1745
|
-
VALUE error;
|
1746
1817
|
|
1818
|
+
rb_check_frozen(self);
|
1747
1819
|
if( PQsetSingleRowMode(conn) == 0 )
|
1748
|
-
|
1749
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
1750
|
-
rb_iv_set(error, "@connection", self);
|
1751
|
-
rb_exc_raise(error);
|
1752
|
-
}
|
1820
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
1753
1821
|
|
1754
1822
|
return self;
|
1755
1823
|
}
|
@@ -1773,15 +1841,12 @@ static VALUE
|
|
1773
1841
|
pgconn_send_query(int argc, VALUE *argv, VALUE self)
|
1774
1842
|
{
|
1775
1843
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1776
|
-
VALUE error;
|
1777
1844
|
|
1778
1845
|
/* If called with no or nil parameters, use PQexec for compatibility */
|
1779
1846
|
if ( argc == 1 || (argc >= 2 && argc <= 4 && NIL_P(argv[1]) )) {
|
1780
|
-
if(gvl_PQsendQuery(this->pgconn, pg_cstr_enc(argv[0], this->enc_idx)) == 0)
|
1781
|
-
|
1782
|
-
|
1783
|
-
rb_exc_raise(error);
|
1784
|
-
}
|
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
|
+
|
1785
1850
|
pgconn_wait_for_flush( self );
|
1786
1851
|
return Qnil;
|
1787
1852
|
}
|
@@ -1838,7 +1903,6 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1838
1903
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1839
1904
|
int result;
|
1840
1905
|
VALUE command, in_res_fmt;
|
1841
|
-
VALUE error;
|
1842
1906
|
int nParams;
|
1843
1907
|
int resultFormat;
|
1844
1908
|
struct query_params_data paramsData = { this->enc_idx };
|
@@ -1855,11 +1919,9 @@ pgconn_send_query_params(int argc, VALUE *argv, VALUE self)
|
|
1855
1919
|
|
1856
1920
|
free_query_params( ¶msData );
|
1857
1921
|
|
1858
|
-
if(result == 0)
|
1859
|
-
|
1860
|
-
|
1861
|
-
rb_exc_raise(error);
|
1862
|
-
}
|
1922
|
+
if(result == 0)
|
1923
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1924
|
+
|
1863
1925
|
pgconn_wait_for_flush( self );
|
1864
1926
|
return Qnil;
|
1865
1927
|
}
|
@@ -1891,7 +1953,6 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1891
1953
|
int result;
|
1892
1954
|
VALUE name, command, in_paramtypes;
|
1893
1955
|
VALUE param;
|
1894
|
-
VALUE error;
|
1895
1956
|
int i = 0;
|
1896
1957
|
int nParams = 0;
|
1897
1958
|
Oid *paramTypes = NULL;
|
@@ -1920,9 +1981,7 @@ pgconn_send_prepare(int argc, VALUE *argv, VALUE self)
|
|
1920
1981
|
xfree(paramTypes);
|
1921
1982
|
|
1922
1983
|
if(result == 0) {
|
1923
|
-
|
1924
|
-
rb_iv_set(error, "@connection", self);
|
1925
|
-
rb_exc_raise(error);
|
1984
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
1926
1985
|
}
|
1927
1986
|
pgconn_wait_for_flush( self );
|
1928
1987
|
return Qnil;
|
@@ -1966,7 +2025,6 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1966
2025
|
t_pg_connection *this = pg_get_connection_safe( self );
|
1967
2026
|
int result;
|
1968
2027
|
VALUE name, in_res_fmt;
|
1969
|
-
VALUE error;
|
1970
2028
|
int nParams;
|
1971
2029
|
int resultFormat;
|
1972
2030
|
struct query_params_data paramsData = { this->enc_idx };
|
@@ -1988,11 +2046,9 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
1988
2046
|
|
1989
2047
|
free_query_params( ¶msData );
|
1990
2048
|
|
1991
|
-
if(result == 0)
|
1992
|
-
|
1993
|
-
|
1994
|
-
rb_exc_raise(error);
|
1995
|
-
}
|
2049
|
+
if(result == 0)
|
2050
|
+
pg_raise_conn_error( rb_eUnableToSend, self, "%s", PQerrorMessage(this->pgconn));
|
2051
|
+
|
1996
2052
|
pgconn_wait_for_flush( self );
|
1997
2053
|
return Qnil;
|
1998
2054
|
}
|
@@ -2007,14 +2063,11 @@ pgconn_send_query_prepared(int argc, VALUE *argv, VALUE self)
|
|
2007
2063
|
static VALUE
|
2008
2064
|
pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
2009
2065
|
{
|
2010
|
-
VALUE error;
|
2011
2066
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2012
2067
|
/* returns 0 on failure */
|
2013
|
-
if(gvl_PQsendDescribePrepared(this->pgconn, pg_cstr_enc(stmt_name, this->enc_idx)) == 0)
|
2014
|
-
|
2015
|
-
|
2016
|
-
rb_exc_raise(error);
|
2017
|
-
}
|
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
|
+
|
2018
2071
|
pgconn_wait_for_flush( self );
|
2019
2072
|
return Qnil;
|
2020
2073
|
}
|
@@ -2030,14 +2083,11 @@ pgconn_send_describe_prepared(VALUE self, VALUE stmt_name)
|
|
2030
2083
|
static VALUE
|
2031
2084
|
pgconn_send_describe_portal(VALUE self, VALUE portal)
|
2032
2085
|
{
|
2033
|
-
VALUE error;
|
2034
2086
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2035
2087
|
/* returns 0 on failure */
|
2036
|
-
if(gvl_PQsendDescribePortal(this->pgconn, pg_cstr_enc(portal, this->enc_idx)) == 0)
|
2037
|
-
|
2038
|
-
|
2039
|
-
rb_exc_raise(error);
|
2040
|
-
}
|
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
|
+
|
2041
2091
|
pgconn_wait_for_flush( self );
|
2042
2092
|
return Qnil;
|
2043
2093
|
}
|
@@ -2070,18 +2120,15 @@ pgconn_sync_get_result(VALUE self)
|
|
2070
2120
|
* or *notifies* to see if the state has changed.
|
2071
2121
|
*/
|
2072
2122
|
static VALUE
|
2073
|
-
pgconn_consume_input(self)
|
2074
|
-
VALUE self;
|
2123
|
+
pgconn_consume_input(VALUE self)
|
2075
2124
|
{
|
2076
|
-
VALUE error;
|
2077
2125
|
PGconn *conn = pg_get_pgconn(self);
|
2078
2126
|
/* returns 0 on error */
|
2079
2127
|
if(PQconsumeInput(conn) == 0) {
|
2080
2128
|
pgconn_close_socket_io(self);
|
2081
|
-
|
2082
|
-
rb_iv_set(error, "@connection", self);
|
2083
|
-
rb_exc_raise(error);
|
2129
|
+
pg_raise_conn_error( rb_eConnectionBad, self, "%s", PQerrorMessage(conn));
|
2084
2130
|
}
|
2131
|
+
|
2085
2132
|
return Qnil;
|
2086
2133
|
}
|
2087
2134
|
|
@@ -2093,19 +2140,17 @@ pgconn_consume_input(self)
|
|
2093
2140
|
* #get_result would block. Otherwise returns +false+.
|
2094
2141
|
*/
|
2095
2142
|
static VALUE
|
2096
|
-
pgconn_is_busy(self)
|
2097
|
-
VALUE self;
|
2143
|
+
pgconn_is_busy(VALUE self)
|
2098
2144
|
{
|
2099
2145
|
return gvl_PQisBusy(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2100
2146
|
}
|
2101
2147
|
|
2102
2148
|
static VALUE
|
2103
|
-
pgconn_sync_setnonblocking(self, state)
|
2104
|
-
VALUE self, state;
|
2149
|
+
pgconn_sync_setnonblocking(VALUE self, VALUE state)
|
2105
2150
|
{
|
2106
2151
|
int arg;
|
2107
|
-
VALUE error;
|
2108
2152
|
PGconn *conn = pg_get_pgconn(self);
|
2153
|
+
rb_check_frozen(self);
|
2109
2154
|
if(state == Qtrue)
|
2110
2155
|
arg = 1;
|
2111
2156
|
else if (state == Qfalse)
|
@@ -2113,18 +2158,15 @@ pgconn_sync_setnonblocking(self, state)
|
|
2113
2158
|
else
|
2114
2159
|
rb_raise(rb_eArgError, "Boolean value expected");
|
2115
2160
|
|
2116
|
-
if(PQsetnonblocking(conn, arg) == -1)
|
2117
|
-
|
2118
|
-
|
2119
|
-
rb_exc_raise(error);
|
2120
|
-
}
|
2161
|
+
if(PQsetnonblocking(conn, arg) == -1)
|
2162
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
2163
|
+
|
2121
2164
|
return Qnil;
|
2122
2165
|
}
|
2123
2166
|
|
2124
2167
|
|
2125
2168
|
static VALUE
|
2126
|
-
pgconn_sync_isnonblocking(self)
|
2127
|
-
VALUE self;
|
2169
|
+
pgconn_sync_isnonblocking(VALUE self)
|
2128
2170
|
{
|
2129
2171
|
return PQisnonblocking(pg_get_pgconn(self)) ? Qtrue : Qfalse;
|
2130
2172
|
}
|
@@ -2133,14 +2175,10 @@ static VALUE
|
|
2133
2175
|
pgconn_sync_flush(VALUE self)
|
2134
2176
|
{
|
2135
2177
|
PGconn *conn = pg_get_pgconn(self);
|
2136
|
-
int ret;
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
error = rb_exc_new2(rb_ePGerror, PQerrorMessage(conn));
|
2141
|
-
rb_iv_set(error, "@connection", self);
|
2142
|
-
rb_exc_raise(error);
|
2143
|
-
}
|
2178
|
+
int ret = PQflush(conn);
|
2179
|
+
if(ret == -1)
|
2180
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
2181
|
+
|
2144
2182
|
return (ret) ? Qfalse : Qtrue;
|
2145
2183
|
}
|
2146
2184
|
|
@@ -2154,7 +2192,7 @@ pgconn_sync_cancel(VALUE self)
|
|
2154
2192
|
|
2155
2193
|
cancel = PQgetCancel(pg_get_pgconn(self));
|
2156
2194
|
if(cancel == NULL)
|
2157
|
-
|
2195
|
+
pg_raise_conn_error( rb_ePGerror, self, "Invalid connection!");
|
2158
2196
|
|
2159
2197
|
ret = gvl_PQcancel(cancel, errbuf, sizeof(errbuf));
|
2160
2198
|
if(ret == 1)
|
@@ -2343,21 +2381,12 @@ pg_rb_io_wait(VALUE io, VALUE events, VALUE timeout) {
|
|
2343
2381
|
static void *
|
2344
2382
|
wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)(PGconn *))
|
2345
2383
|
{
|
2346
|
-
VALUE socket_io;
|
2347
2384
|
VALUE ret;
|
2348
2385
|
void *retval;
|
2349
2386
|
struct timeval aborttime={0,0}, currtime, waittime;
|
2350
2387
|
VALUE wait_timeout = Qnil;
|
2351
2388
|
PGconn *conn = pg_get_pgconn(self);
|
2352
2389
|
|
2353
|
-
socket_io = pgconn_socket_io(self);
|
2354
|
-
|
2355
|
-
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2356
|
-
if ( PQconsumeInput(conn) == 0 ) {
|
2357
|
-
pgconn_close_socket_io(self);
|
2358
|
-
rb_raise( rb_eConnectionBad, "PQconsumeInput() %s", PQerrorMessage(conn) );
|
2359
|
-
}
|
2360
|
-
|
2361
2390
|
if ( ptimeout ) {
|
2362
2391
|
gettimeofday(&currtime, NULL);
|
2363
2392
|
timeradd(&currtime, ptimeout, &aborttime);
|
@@ -2372,6 +2401,14 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
2372
2401
|
|
2373
2402
|
/* Is the given timeout valid? */
|
2374
2403
|
if( !ptimeout || (waittime.tv_sec >= 0 && waittime.tv_usec >= 0) ){
|
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);
|
2375
2412
|
/* Wait for the socket to become readable before checking again */
|
2376
2413
|
ret = pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), wait_timeout);
|
2377
2414
|
} else {
|
@@ -2386,7 +2423,7 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
2386
2423
|
/* Check for connection errors (PQisBusy is true on connection errors) */
|
2387
2424
|
if ( PQconsumeInput(conn) == 0 ){
|
2388
2425
|
pgconn_close_socket_io(self);
|
2389
|
-
|
2426
|
+
pg_raise_conn_error(rb_eConnectionBad, self, "PQconsumeInput() %s", PQerrorMessage(conn));
|
2390
2427
|
}
|
2391
2428
|
}
|
2392
2429
|
|
@@ -2399,8 +2436,8 @@ wait_socket_readable( VALUE self, struct timeval *ptimeout, void *(*is_readable)
|
|
2399
2436
|
*
|
2400
2437
|
* Attempts to flush any queued output data to the server.
|
2401
2438
|
* Returns +true+ if data is successfully flushed, +false+
|
2402
|
-
* if not
|
2403
|
-
* nonblocking.
|
2439
|
+
* if not. It can only return +false+ if connection is
|
2440
|
+
* in nonblocking mode.
|
2404
2441
|
* Raises PG::Error if some other failure occurred.
|
2405
2442
|
*/
|
2406
2443
|
static VALUE
|
@@ -2412,8 +2449,9 @@ pgconn_async_flush(VALUE self)
|
|
2412
2449
|
VALUE socket_io = pgconn_socket_io(self);
|
2413
2450
|
events = RB_NUM2INT(pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE | PG_RUBY_IO_WRITABLE), Qnil));
|
2414
2451
|
|
2415
|
-
if (events & PG_RUBY_IO_READABLE)
|
2452
|
+
if (events & PG_RUBY_IO_READABLE){
|
2416
2453
|
pgconn_consume_input(self);
|
2454
|
+
}
|
2417
2455
|
}
|
2418
2456
|
return Qtrue;
|
2419
2457
|
}
|
@@ -2429,6 +2467,7 @@ pgconn_wait_for_flush( VALUE self ){
|
|
2429
2467
|
static VALUE
|
2430
2468
|
pgconn_flush_data_set( VALUE self, VALUE enabled ){
|
2431
2469
|
t_pg_connection *conn = pg_get_connection(self);
|
2470
|
+
rb_check_frozen(self);
|
2432
2471
|
conn->flush_data = RTEST(enabled);
|
2433
2472
|
return enabled;
|
2434
2473
|
}
|
@@ -2536,11 +2575,9 @@ pgconn_sync_put_copy_data(int argc, VALUE *argv, VALUE self)
|
|
2536
2575
|
Check_Type(buffer, T_STRING);
|
2537
2576
|
|
2538
2577
|
ret = gvl_PQputCopyData(this->pgconn, RSTRING_PTR(buffer), RSTRING_LENINT(buffer));
|
2539
|
-
if(ret == -1)
|
2540
|
-
|
2541
|
-
|
2542
|
-
rb_exc_raise(error);
|
2543
|
-
}
|
2578
|
+
if(ret == -1)
|
2579
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2580
|
+
|
2544
2581
|
RB_GC_GUARD(intermediate);
|
2545
2582
|
RB_GC_GUARD(buffer);
|
2546
2583
|
|
@@ -2551,7 +2588,6 @@ static VALUE
|
|
2551
2588
|
pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
2552
2589
|
{
|
2553
2590
|
VALUE str;
|
2554
|
-
VALUE error;
|
2555
2591
|
int ret;
|
2556
2592
|
const char *error_message = NULL;
|
2557
2593
|
t_pg_connection *this = pg_get_connection_safe( self );
|
@@ -2562,11 +2598,9 @@ pgconn_sync_put_copy_end(int argc, VALUE *argv, VALUE self)
|
|
2562
2598
|
error_message = pg_cstr_enc(str, this->enc_idx);
|
2563
2599
|
|
2564
2600
|
ret = gvl_PQputCopyEnd(this->pgconn, error_message);
|
2565
|
-
if(ret == -1)
|
2566
|
-
|
2567
|
-
|
2568
|
-
rb_exc_raise(error);
|
2569
|
-
}
|
2601
|
+
if(ret == -1)
|
2602
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2603
|
+
|
2570
2604
|
return (ret) ? Qtrue : Qfalse;
|
2571
2605
|
}
|
2572
2606
|
|
@@ -2574,7 +2608,6 @@ static VALUE
|
|
2574
2608
|
pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
2575
2609
|
{
|
2576
2610
|
VALUE async_in;
|
2577
|
-
VALUE error;
|
2578
2611
|
VALUE result;
|
2579
2612
|
int ret;
|
2580
2613
|
char *buffer;
|
@@ -2594,10 +2627,8 @@ pgconn_sync_get_copy_data(int argc, VALUE *argv, VALUE self )
|
|
2594
2627
|
}
|
2595
2628
|
|
2596
2629
|
ret = gvl_PQgetCopyData(this->pgconn, &buffer, RTEST(async_in));
|
2597
|
-
if(ret == -2)
|
2598
|
-
|
2599
|
-
rb_iv_set(error, "@connection", self);
|
2600
|
-
rb_exc_raise(error);
|
2630
|
+
if(ret == -2){ /* error */
|
2631
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(this->pgconn));
|
2601
2632
|
}
|
2602
2633
|
if(ret == -1) { /* No data left */
|
2603
2634
|
return Qnil;
|
@@ -2691,6 +2722,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2691
2722
|
VALUE new_file;
|
2692
2723
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2693
2724
|
|
2725
|
+
rb_check_frozen(self);
|
2694
2726
|
if(!rb_respond_to(stream,rb_intern("fileno")))
|
2695
2727
|
rb_raise(rb_eArgError, "stream does not respond to method: fileno");
|
2696
2728
|
|
@@ -2712,7 +2744,7 @@ pgconn_trace(VALUE self, VALUE stream)
|
|
2712
2744
|
rb_raise(rb_eArgError, "stream is not writable");
|
2713
2745
|
|
2714
2746
|
new_file = rb_funcall(rb_cIO, rb_intern("new"), 1, INT2NUM(new_fd));
|
2715
|
-
this->trace_stream
|
2747
|
+
RB_OBJ_WRITE(self, &this->trace_stream, new_file);
|
2716
2748
|
|
2717
2749
|
PQtrace(this->pgconn, new_fp);
|
2718
2750
|
return Qnil;
|
@@ -2731,7 +2763,7 @@ pgconn_untrace(VALUE self)
|
|
2731
2763
|
|
2732
2764
|
PQuntrace(this->pgconn);
|
2733
2765
|
rb_funcall(this->trace_stream, rb_intern("close"), 0);
|
2734
|
-
this->trace_stream
|
2766
|
+
RB_OBJ_WRITE(self, &this->trace_stream, Qnil);
|
2735
2767
|
return Qnil;
|
2736
2768
|
}
|
2737
2769
|
|
@@ -2790,13 +2822,14 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2790
2822
|
VALUE proc, old_proc;
|
2791
2823
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2792
2824
|
|
2825
|
+
rb_check_frozen(self);
|
2793
2826
|
/* If default_notice_receiver is unset, assume that the current
|
2794
2827
|
* notice receiver is the default, and save it to a global variable.
|
2795
2828
|
* This should not be a problem because the default receiver is
|
2796
2829
|
* always the same, so won't vary among connections.
|
2797
2830
|
*/
|
2798
|
-
if(default_notice_receiver == NULL)
|
2799
|
-
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);
|
2800
2833
|
|
2801
2834
|
old_proc = this->notice_receiver;
|
2802
2835
|
if( rb_block_given_p() ) {
|
@@ -2805,10 +2838,10 @@ pgconn_set_notice_receiver(VALUE self)
|
|
2805
2838
|
} else {
|
2806
2839
|
/* if no block is given, set back to default */
|
2807
2840
|
proc = Qnil;
|
2808
|
-
PQsetNoticeReceiver(this->pgconn, default_notice_receiver, NULL);
|
2841
|
+
PQsetNoticeReceiver(this->pgconn, this->default_notice_receiver, NULL);
|
2809
2842
|
}
|
2810
2843
|
|
2811
|
-
this->notice_receiver
|
2844
|
+
RB_OBJ_WRITE(self, &this->notice_receiver, proc);
|
2812
2845
|
return old_proc;
|
2813
2846
|
}
|
2814
2847
|
|
@@ -2823,10 +2856,10 @@ notice_processor_proxy(void *arg, const char *message)
|
|
2823
2856
|
VALUE self = (VALUE)arg;
|
2824
2857
|
t_pg_connection *this = pg_get_connection( self );
|
2825
2858
|
|
2826
|
-
if (this->
|
2859
|
+
if (this->notice_processor != Qnil) {
|
2827
2860
|
VALUE message_str = rb_str_new2(message);
|
2828
2861
|
PG_ENCODING_SET_NOCHECK( message_str, this->enc_idx );
|
2829
|
-
rb_funcall(this->
|
2862
|
+
rb_funcall(this->notice_processor, rb_intern("call"), 1, message_str);
|
2830
2863
|
}
|
2831
2864
|
return;
|
2832
2865
|
}
|
@@ -2850,25 +2883,26 @@ pgconn_set_notice_processor(VALUE self)
|
|
2850
2883
|
VALUE proc, old_proc;
|
2851
2884
|
t_pg_connection *this = pg_get_connection_safe( self );
|
2852
2885
|
|
2886
|
+
rb_check_frozen(self);
|
2853
2887
|
/* If default_notice_processor is unset, assume that the current
|
2854
2888
|
* notice processor is the default, and save it to a global variable.
|
2855
2889
|
* This should not be a problem because the default processor is
|
2856
2890
|
* always the same, so won't vary among connections.
|
2857
2891
|
*/
|
2858
|
-
if(default_notice_processor == NULL)
|
2859
|
-
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);
|
2860
2894
|
|
2861
|
-
old_proc = this->
|
2895
|
+
old_proc = this->notice_processor;
|
2862
2896
|
if( rb_block_given_p() ) {
|
2863
2897
|
proc = rb_block_proc();
|
2864
2898
|
PQsetNoticeProcessor(this->pgconn, gvl_notice_processor_proxy, (void *)self);
|
2865
2899
|
} else {
|
2866
2900
|
/* if no block is given, set back to default */
|
2867
2901
|
proc = Qnil;
|
2868
|
-
PQsetNoticeProcessor(this->pgconn, default_notice_processor, NULL);
|
2902
|
+
PQsetNoticeProcessor(this->pgconn, this->default_notice_processor, NULL);
|
2869
2903
|
}
|
2870
2904
|
|
2871
|
-
this->
|
2905
|
+
RB_OBJ_WRITE(self, &this->notice_processor, proc);
|
2872
2906
|
return old_proc;
|
2873
2907
|
}
|
2874
2908
|
|
@@ -2900,11 +2934,12 @@ pgconn_sync_set_client_encoding(VALUE self, VALUE str)
|
|
2900
2934
|
{
|
2901
2935
|
PGconn *conn = pg_get_pgconn( self );
|
2902
2936
|
|
2937
|
+
rb_check_frozen(self);
|
2903
2938
|
Check_Type(str, T_STRING);
|
2904
2939
|
|
2905
|
-
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
2906
|
-
|
2907
|
-
|
2940
|
+
if ( (gvl_PQsetClientEncoding(conn, StringValueCStr(str))) == -1 )
|
2941
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
2942
|
+
|
2908
2943
|
pgconn_set_internal_encoding_index( self );
|
2909
2944
|
|
2910
2945
|
return Qnil;
|
@@ -2984,7 +3019,7 @@ get_result_readable(PGconn *conn)
|
|
2984
3019
|
* If +true+ is returned, +conn.is_busy+ will return +false+
|
2985
3020
|
* and +conn.get_result+ will not block.
|
2986
3021
|
*/
|
2987
|
-
|
3022
|
+
VALUE
|
2988
3023
|
pgconn_block( int argc, VALUE *argv, VALUE self ) {
|
2989
3024
|
struct timeval timeout;
|
2990
3025
|
struct timeval *ptimeout = NULL;
|
@@ -3068,11 +3103,12 @@ pgconn_async_get_last_result(VALUE self)
|
|
3068
3103
|
VALUE rb_pgresult = Qnil;
|
3069
3104
|
PGresult *cur, *prev;
|
3070
3105
|
|
3071
|
-
|
3106
|
+
cur = prev = NULL;
|
3072
3107
|
for(;;) {
|
3073
3108
|
int status;
|
3074
3109
|
|
3075
|
-
|
3110
|
+
/* wait for input (without blocking) before reading each result */
|
3111
|
+
wait_socket_readable(self, NULL, get_result_readable);
|
3076
3112
|
|
3077
3113
|
cur = gvl_PQgetResult(conn);
|
3078
3114
|
if (cur == NULL)
|
@@ -3099,8 +3135,14 @@ pgconn_async_get_last_result(VALUE self)
|
|
3099
3135
|
* conn.discard_results()
|
3100
3136
|
*
|
3101
3137
|
* Silently discard any prior query result that application didn't eat.
|
3102
|
-
* This is
|
3103
|
-
*
|
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
|
+
*
|
3104
3146
|
*/
|
3105
3147
|
static VALUE
|
3106
3148
|
pgconn_discard_results(VALUE self)
|
@@ -3108,8 +3150,12 @@ pgconn_discard_results(VALUE self)
|
|
3108
3150
|
PGconn *conn = pg_get_pgconn(self);
|
3109
3151
|
VALUE socket_io;
|
3110
3152
|
|
3111
|
-
|
3112
|
-
|
3153
|
+
switch( PQtransactionStatus(conn) ) {
|
3154
|
+
case PQTRANS_IDLE:
|
3155
|
+
case PQTRANS_INTRANS:
|
3156
|
+
case PQTRANS_INERROR:
|
3157
|
+
return Qnil;
|
3158
|
+
default:;
|
3113
3159
|
}
|
3114
3160
|
|
3115
3161
|
socket_io = pgconn_socket_io(self);
|
@@ -3122,10 +3168,21 @@ pgconn_discard_results(VALUE self)
|
|
3122
3168
|
* To avoid this call pg_rb_io_wait() and PQconsumeInput() without rb_raise().
|
3123
3169
|
*/
|
3124
3170
|
while( gvl_PQisBusy(conn) ){
|
3125
|
-
|
3126
|
-
|
3127
|
-
|
3128
|
-
|
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;
|
3129
3186
|
}
|
3130
3187
|
}
|
3131
3188
|
|
@@ -3135,7 +3192,9 @@ pgconn_discard_results(VALUE self)
|
|
3135
3192
|
status = PQresultStatus(cur);
|
3136
3193
|
PQclear(cur);
|
3137
3194
|
if (status == PGRES_COPY_IN){
|
3138
|
-
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
|
+
}
|
3139
3198
|
}
|
3140
3199
|
if (status == PGRES_COPY_OUT){
|
3141
3200
|
for(;;) {
|
@@ -3144,10 +3203,7 @@ pgconn_discard_results(VALUE self)
|
|
3144
3203
|
if( st == 0 ) {
|
3145
3204
|
/* would block -> wait for readable data */
|
3146
3205
|
pg_rb_io_wait(socket_io, RB_INT2NUM(PG_RUBY_IO_READABLE), Qnil);
|
3147
|
-
if ( PQconsumeInput(conn) == 0 )
|
3148
|
-
pgconn_close_socket_io(self);
|
3149
|
-
return Qfalse;
|
3150
|
-
}
|
3206
|
+
if ( PQconsumeInput(conn) == 0 ) goto error;
|
3151
3207
|
} else if( st > 0 ) {
|
3152
3208
|
/* some data retrieved -> discard it */
|
3153
3209
|
PQfreemem(buffer);
|
@@ -3160,6 +3216,10 @@ pgconn_discard_results(VALUE self)
|
|
3160
3216
|
}
|
3161
3217
|
|
3162
3218
|
return Qtrue;
|
3219
|
+
|
3220
|
+
error:
|
3221
|
+
pgconn_close_socket_io(self);
|
3222
|
+
return Qfalse;
|
3163
3223
|
}
|
3164
3224
|
|
3165
3225
|
/*
|
@@ -3536,11 +3596,10 @@ pgconn_enter_pipeline_mode(VALUE self)
|
|
3536
3596
|
{
|
3537
3597
|
PGconn *conn = pg_get_pgconn(self);
|
3538
3598
|
int res = PQenterPipelineMode(conn);
|
3539
|
-
if( res
|
3540
|
-
|
3541
|
-
|
3542
|
-
|
3543
|
-
}
|
3599
|
+
if( res != 1 )
|
3600
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3601
|
+
|
3602
|
+
return Qnil;
|
3544
3603
|
}
|
3545
3604
|
|
3546
3605
|
/*
|
@@ -3559,11 +3618,10 @@ pgconn_exit_pipeline_mode(VALUE self)
|
|
3559
3618
|
{
|
3560
3619
|
PGconn *conn = pg_get_pgconn(self);
|
3561
3620
|
int res = PQexitPipelineMode(conn);
|
3562
|
-
if( res
|
3563
|
-
|
3564
|
-
|
3565
|
-
|
3566
|
-
}
|
3621
|
+
if( res != 1 )
|
3622
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3623
|
+
|
3624
|
+
return Qnil;
|
3567
3625
|
}
|
3568
3626
|
|
3569
3627
|
|
@@ -3583,11 +3641,10 @@ pgconn_pipeline_sync(VALUE self)
|
|
3583
3641
|
{
|
3584
3642
|
PGconn *conn = pg_get_pgconn(self);
|
3585
3643
|
int res = PQpipelineSync(conn);
|
3586
|
-
if( res
|
3587
|
-
|
3588
|
-
|
3589
|
-
|
3590
|
-
}
|
3644
|
+
if( res != 1 )
|
3645
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3646
|
+
|
3647
|
+
return Qnil;
|
3591
3648
|
}
|
3592
3649
|
|
3593
3650
|
/*
|
@@ -3607,11 +3664,10 @@ pgconn_send_flush_request(VALUE self)
|
|
3607
3664
|
{
|
3608
3665
|
PGconn *conn = pg_get_pgconn(self);
|
3609
3666
|
int res = PQsendFlushRequest(conn);
|
3610
|
-
if( res
|
3611
|
-
|
3612
|
-
|
3613
|
-
|
3614
|
-
}
|
3667
|
+
if( res != 1 )
|
3668
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3669
|
+
|
3670
|
+
return Qnil;
|
3615
3671
|
}
|
3616
3672
|
|
3617
3673
|
#endif
|
@@ -3620,6 +3676,14 @@ pgconn_send_flush_request(VALUE self)
|
|
3620
3676
|
* LARGE OBJECT SUPPORT
|
3621
3677
|
**************************************************************************/
|
3622
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
|
+
|
3623
3687
|
/*
|
3624
3688
|
* call-seq:
|
3625
3689
|
* conn.lo_creat( [mode] ) -> Integer
|
@@ -3640,9 +3704,12 @@ pgconn_locreat(int argc, VALUE *argv, VALUE self)
|
|
3640
3704
|
else
|
3641
3705
|
mode = NUM2INT(nmode);
|
3642
3706
|
|
3643
|
-
|
3707
|
+
BLOCKING_BEGIN(conn)
|
3708
|
+
lo_oid = lo_creat(conn, mode);
|
3709
|
+
BLOCKING_END(conn)
|
3710
|
+
|
3644
3711
|
if (lo_oid == 0)
|
3645
|
-
|
3712
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_creat failed");
|
3646
3713
|
|
3647
3714
|
return UINT2NUM(lo_oid);
|
3648
3715
|
}
|
@@ -3663,7 +3730,7 @@ pgconn_locreate(VALUE self, VALUE in_lo_oid)
|
|
3663
3730
|
|
3664
3731
|
ret = lo_create(conn, lo_oid);
|
3665
3732
|
if (ret == InvalidOid)
|
3666
|
-
|
3733
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_create failed");
|
3667
3734
|
|
3668
3735
|
return UINT2NUM(ret);
|
3669
3736
|
}
|
@@ -3685,9 +3752,12 @@ pgconn_loimport(VALUE self, VALUE filename)
|
|
3685
3752
|
|
3686
3753
|
Check_Type(filename, T_STRING);
|
3687
3754
|
|
3688
|
-
|
3755
|
+
BLOCKING_BEGIN(conn)
|
3756
|
+
lo_oid = lo_import(conn, StringValueCStr(filename));
|
3757
|
+
BLOCKING_END(conn)
|
3758
|
+
|
3689
3759
|
if (lo_oid == 0) {
|
3690
|
-
|
3760
|
+
pg_raise_conn_error( rb_ePGerror, self, "%s", PQerrorMessage(conn));
|
3691
3761
|
}
|
3692
3762
|
return UINT2NUM(lo_oid);
|
3693
3763
|
}
|
@@ -3703,12 +3773,17 @@ pgconn_loexport(VALUE self, VALUE lo_oid, VALUE filename)
|
|
3703
3773
|
{
|
3704
3774
|
PGconn *conn = pg_get_pgconn(self);
|
3705
3775
|
Oid oid;
|
3776
|
+
int ret;
|
3706
3777
|
Check_Type(filename, T_STRING);
|
3707
3778
|
|
3708
3779
|
oid = NUM2UINT(lo_oid);
|
3709
3780
|
|
3710
|
-
|
3711
|
-
|
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));
|
3712
3787
|
}
|
3713
3788
|
return Qnil;
|
3714
3789
|
}
|
@@ -3738,8 +3813,12 @@ pgconn_loopen(int argc, VALUE *argv, VALUE self)
|
|
3738
3813
|
else
|
3739
3814
|
mode = NUM2INT(nmode);
|
3740
3815
|
|
3741
|
-
|
3742
|
-
|
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));
|
3743
3822
|
}
|
3744
3823
|
return INT2FIX(fd);
|
3745
3824
|
}
|
@@ -3761,11 +3840,15 @@ pgconn_lowrite(VALUE self, VALUE in_lo_desc, VALUE buffer)
|
|
3761
3840
|
Check_Type(buffer, T_STRING);
|
3762
3841
|
|
3763
3842
|
if( RSTRING_LEN(buffer) < 0) {
|
3764
|
-
|
3843
|
+
pg_raise_conn_error( rb_ePGerror, self, "write buffer zero string");
|
3765
3844
|
}
|
3766
|
-
|
3767
|
-
|
3768
|
-
|
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));
|
3769
3852
|
}
|
3770
3853
|
|
3771
3854
|
return INT2FIX(n);
|
@@ -3788,16 +3871,17 @@ pgconn_loread(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3788
3871
|
VALUE str;
|
3789
3872
|
char *buffer;
|
3790
3873
|
|
3791
|
-
|
3792
|
-
|
3793
|
-
rb_raise(rb_eNoMemError, "ALLOC failed!");
|
3874
|
+
if (len < 0)
|
3875
|
+
pg_raise_conn_error( rb_ePGerror, self, "negative length %d given", len);
|
3794
3876
|
|
3795
|
-
|
3796
|
-
rb_raise(rb_ePGerror,"nagative length %d given", len);
|
3797
|
-
}
|
3877
|
+
buffer = ALLOC_N(char, len);
|
3798
3878
|
|
3799
|
-
|
3800
|
-
|
3879
|
+
BLOCKING_BEGIN(conn)
|
3880
|
+
ret = lo_read(conn, lo_desc, buffer, len);
|
3881
|
+
BLOCKING_END(conn)
|
3882
|
+
|
3883
|
+
if(ret < 0)
|
3884
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_read failed");
|
3801
3885
|
|
3802
3886
|
if(ret == 0) {
|
3803
3887
|
xfree(buffer);
|
@@ -3826,8 +3910,12 @@ pgconn_lolseek(VALUE self, VALUE in_lo_desc, VALUE offset, VALUE whence)
|
|
3826
3910
|
int lo_desc = NUM2INT(in_lo_desc);
|
3827
3911
|
int ret;
|
3828
3912
|
|
3829
|
-
|
3830
|
-
|
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");
|
3831
3919
|
}
|
3832
3920
|
|
3833
3921
|
return INT2FIX(ret);
|
@@ -3846,8 +3934,12 @@ pgconn_lotell(VALUE self, VALUE in_lo_desc)
|
|
3846
3934
|
PGconn *conn = pg_get_pgconn(self);
|
3847
3935
|
int lo_desc = NUM2INT(in_lo_desc);
|
3848
3936
|
|
3849
|
-
|
3850
|
-
|
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");
|
3851
3943
|
|
3852
3944
|
return INT2FIX(position);
|
3853
3945
|
}
|
@@ -3864,9 +3956,14 @@ pgconn_lotruncate(VALUE self, VALUE in_lo_desc, VALUE in_len)
|
|
3864
3956
|
PGconn *conn = pg_get_pgconn(self);
|
3865
3957
|
int lo_desc = NUM2INT(in_lo_desc);
|
3866
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)
|
3867
3964
|
|
3868
|
-
if(
|
3869
|
-
|
3965
|
+
if(ret < 0)
|
3966
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_truncate failed");
|
3870
3967
|
|
3871
3968
|
return Qnil;
|
3872
3969
|
}
|
@@ -3882,9 +3979,14 @@ pgconn_loclose(VALUE self, VALUE in_lo_desc)
|
|
3882
3979
|
{
|
3883
3980
|
PGconn *conn = pg_get_pgconn(self);
|
3884
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)
|
3885
3987
|
|
3886
|
-
if(
|
3887
|
-
|
3988
|
+
if(ret < 0)
|
3989
|
+
pg_raise_conn_error( rb_ePGerror, self, "lo_close failed");
|
3888
3990
|
|
3889
3991
|
return Qnil;
|
3890
3992
|
}
|
@@ -3900,9 +4002,14 @@ pgconn_lounlink(VALUE self, VALUE in_oid)
|
|
3900
4002
|
{
|
3901
4003
|
PGconn *conn = pg_get_pgconn(self);
|
3902
4004
|
Oid oid = NUM2UINT(in_oid);
|
4005
|
+
int ret;
|
3903
4006
|
|
3904
|
-
|
3905
|
-
|
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");
|
3906
4013
|
|
3907
4014
|
return Qnil;
|
3908
4015
|
}
|
@@ -3959,6 +4066,7 @@ static VALUE pgconn_external_encoding(VALUE self);
|
|
3959
4066
|
static VALUE
|
3960
4067
|
pgconn_internal_encoding_set(VALUE self, VALUE enc)
|
3961
4068
|
{
|
4069
|
+
rb_check_frozen(self);
|
3962
4070
|
if (NIL_P(enc)) {
|
3963
4071
|
pgconn_sync_set_client_encoding( self, rb_usascii_str_new_cstr("SQL_ASCII") );
|
3964
4072
|
return enc;
|
@@ -4013,6 +4121,7 @@ pgconn_async_set_client_encoding(VALUE self, VALUE encname)
|
|
4013
4121
|
{
|
4014
4122
|
VALUE query_format, query;
|
4015
4123
|
|
4124
|
+
rb_check_frozen(self);
|
4016
4125
|
Check_Type(encname, T_STRING);
|
4017
4126
|
query_format = rb_str_new_cstr("set client_encoding to '%s'");
|
4018
4127
|
query = rb_funcall(query_format, rb_intern("%"), 1, encname);
|
@@ -4065,6 +4174,7 @@ pgconn_set_default_encoding( VALUE self )
|
|
4065
4174
|
rb_encoding *enc;
|
4066
4175
|
const char *encname;
|
4067
4176
|
|
4177
|
+
rb_check_frozen(self);
|
4068
4178
|
if (( enc = rb_default_internal_encoding() )) {
|
4069
4179
|
encname = pg_get_rb_encoding_as_pg_encoding( enc );
|
4070
4180
|
if ( pgconn_set_client_encoding_async(self, rb_str_new_cstr(encname)) != 0 )
|
@@ -4094,10 +4204,11 @@ pgconn_type_map_for_queries_set(VALUE self, VALUE typemap)
|
|
4094
4204
|
t_typemap *tm;
|
4095
4205
|
UNUSED(tm);
|
4096
4206
|
|
4207
|
+
rb_check_frozen(self);
|
4097
4208
|
/* Check type of method param */
|
4098
4209
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4099
4210
|
|
4100
|
-
this->type_map_for_queries
|
4211
|
+
RB_OBJ_WRITE(self, &this->type_map_for_queries, typemap);
|
4101
4212
|
|
4102
4213
|
return typemap;
|
4103
4214
|
}
|
@@ -4134,8 +4245,9 @@ pgconn_type_map_for_results_set(VALUE self, VALUE typemap)
|
|
4134
4245
|
t_typemap *tm;
|
4135
4246
|
UNUSED(tm);
|
4136
4247
|
|
4248
|
+
rb_check_frozen(self);
|
4137
4249
|
TypedData_Get_Struct(typemap, t_typemap, &pg_typemap_type, tm);
|
4138
|
-
this->type_map_for_results
|
4250
|
+
RB_OBJ_WRITE(self, &this->type_map_for_results, typemap);
|
4139
4251
|
|
4140
4252
|
return typemap;
|
4141
4253
|
}
|
@@ -4173,13 +4285,14 @@ pgconn_encoder_for_put_copy_data_set(VALUE self, VALUE encoder)
|
|
4173
4285
|
{
|
4174
4286
|
t_pg_connection *this = pg_get_connection( self );
|
4175
4287
|
|
4288
|
+
rb_check_frozen(self);
|
4176
4289
|
if( encoder != Qnil ){
|
4177
4290
|
t_pg_coder *co;
|
4178
4291
|
UNUSED(co);
|
4179
4292
|
/* Check argument type */
|
4180
4293
|
TypedData_Get_Struct(encoder, t_pg_coder, &pg_coder_type, co);
|
4181
4294
|
}
|
4182
|
-
this->encoder_for_put_copy_data
|
4295
|
+
RB_OBJ_WRITE(self, &this->encoder_for_put_copy_data, encoder);
|
4183
4296
|
|
4184
4297
|
return encoder;
|
4185
4298
|
}
|
@@ -4221,13 +4334,14 @@ pgconn_decoder_for_get_copy_data_set(VALUE self, VALUE decoder)
|
|
4221
4334
|
{
|
4222
4335
|
t_pg_connection *this = pg_get_connection( self );
|
4223
4336
|
|
4337
|
+
rb_check_frozen(self);
|
4224
4338
|
if( decoder != Qnil ){
|
4225
4339
|
t_pg_coder *co;
|
4226
4340
|
UNUSED(co);
|
4227
4341
|
/* Check argument type */
|
4228
4342
|
TypedData_Get_Struct(decoder, t_pg_coder, &pg_coder_type, co);
|
4229
4343
|
}
|
4230
|
-
this->decoder_for_get_copy_data
|
4344
|
+
RB_OBJ_WRITE(self, &this->decoder_for_get_copy_data, decoder);
|
4231
4345
|
|
4232
4346
|
return decoder;
|
4233
4347
|
}
|
@@ -4273,6 +4387,7 @@ pgconn_field_name_type_set(VALUE self, VALUE sym)
|
|
4273
4387
|
{
|
4274
4388
|
t_pg_connection *this = pg_get_connection( self );
|
4275
4389
|
|
4390
|
+
rb_check_frozen(self);
|
4276
4391
|
this->flags &= ~PG_RESULT_FIELD_NAMES_MASK;
|
4277
4392
|
if( sym == sym_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_SYMBOL;
|
4278
4393
|
else if ( sym == sym_static_symbol ) this->flags |= PG_RESULT_FIELD_NAMES_STATIC_SYMBOL;
|
@@ -4309,7 +4424,7 @@ pgconn_field_name_type_get(VALUE self)
|
|
4309
4424
|
* Document-class: PG::Connection
|
4310
4425
|
*/
|
4311
4426
|
void
|
4312
|
-
init_pg_connection()
|
4427
|
+
init_pg_connection(void)
|
4313
4428
|
{
|
4314
4429
|
s_id_encode = rb_intern("encode");
|
4315
4430
|
s_id_autoclose_set = rb_intern("autoclose=");
|
@@ -4336,6 +4451,7 @@ init_pg_connection()
|
|
4336
4451
|
rb_define_singleton_method(rb_cPGconn, "quote_ident", pgconn_s_quote_ident, 1);
|
4337
4452
|
rb_define_singleton_method(rb_cPGconn, "connect_start", pgconn_s_connect_start, -1);
|
4338
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);
|
4339
4455
|
rb_define_singleton_method(rb_cPGconn, "sync_ping", pgconn_s_sync_ping, -1);
|
4340
4456
|
rb_define_singleton_method(rb_cPGconn, "sync_connect", pgconn_s_sync_connect, -1);
|
4341
4457
|
|
@@ -4353,6 +4469,9 @@ init_pg_connection()
|
|
4353
4469
|
rb_define_method(rb_cPGconn, "user", pgconn_user, 0);
|
4354
4470
|
rb_define_method(rb_cPGconn, "pass", pgconn_pass, 0);
|
4355
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
|
4356
4475
|
rb_define_method(rb_cPGconn, "port", pgconn_port, 0);
|
4357
4476
|
rb_define_method(rb_cPGconn, "tty", pgconn_tty, 0);
|
4358
4477
|
rb_define_method(rb_cPGconn, "conninfo", pgconn_conninfo, 0);
|