pg 1.5.9-x64-mingw32 → 1.6.0.rc1-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/Gemfile +7 -4
- data/History.md +26 -0
- data/README-Windows.rdoc +1 -1
- data/README.ja.md +3 -3
- data/README.md +4 -4
- data/Rakefile +55 -12
- data/ext/extconf.rb +119 -13
- data/ext/gvl_wrappers.c +13 -2
- data/ext/gvl_wrappers.h +33 -0
- data/ext/pg.c +16 -5
- data/ext/pg.h +8 -9
- data/ext/pg_binary_decoder.c +150 -0
- data/ext/pg_binary_encoder.c +203 -7
- data/ext/pg_cancel_connection.c +360 -0
- data/ext/pg_coder.c +3 -5
- data/ext/pg_connection.c +337 -148
- data/ext/pg_copy_coder.c +2 -2
- data/ext/pg_record_coder.c +1 -1
- data/ext/pg_result.c +9 -11
- data/ext/pg_text_encoder.c +2 -2
- data/ext/pg_tuple.c +2 -2
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +1 -1
- data/ext/pg_type_map_by_class.c +1 -1
- data/ext/pg_type_map_by_column.c +1 -1
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +1 -1
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/lib/2.7/pg_ext.so +0 -0
- data/lib/3.0/pg_ext.so +0 -0
- data/lib/pg/basic_type_registry.rb +2 -2
- data/lib/pg/cancel_connection.rb +30 -0
- data/lib/pg/connection.rb +182 -126
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +13 -8
- data/pg.gemspec +2 -2
- data/{lib/x64-mingw32 → ports/x64-mingw32/lib}/libpq.dll +0 -0
- data.tar.gz.sig +0 -0
- metadata +11 -10
- metadata.gz.sig +0 -0
- data/Rakefile.cross +0 -303
- data/lib/2.5/pg_ext.so +0 -0
- data/lib/2.6/pg_ext.so +0 -0
data/ext/pg_copy_coder.c
CHANGED
@@ -51,7 +51,7 @@ static const rb_data_type_t pg_copycoder_type = {
|
|
51
51
|
pg_copycoder_mark,
|
52
52
|
RUBY_TYPED_DEFAULT_FREE,
|
53
53
|
pg_copycoder_memsize,
|
54
|
-
|
54
|
+
pg_copycoder_compact,
|
55
55
|
},
|
56
56
|
&pg_coder_type,
|
57
57
|
0,
|
@@ -831,7 +831,6 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
831
831
|
|
832
832
|
for( fieldno = 0; fieldno < nfields; fieldno++){
|
833
833
|
long input_len;
|
834
|
-
VALUE field_value;
|
835
834
|
|
836
835
|
/* read field size */
|
837
836
|
if (line_end_ptr - cur_ptr < 4 ) goto length_error;
|
@@ -843,6 +842,7 @@ pg_bin_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tupl
|
|
843
842
|
/* NULL indicator */
|
844
843
|
rb_ary_push(array, Qnil);
|
845
844
|
} else {
|
845
|
+
VALUE field_value;
|
846
846
|
if (line_end_ptr - cur_ptr < input_len ) goto length_error;
|
847
847
|
|
848
848
|
/* copy input data to field_str */
|
data/ext/pg_record_coder.c
CHANGED
data/ext/pg_result.c
CHANGED
@@ -147,9 +147,7 @@ pgresult_clear( void *_this )
|
|
147
147
|
t_pg_result *this = (t_pg_result *)_this;
|
148
148
|
if( this->pgresult && !this->autoclear ){
|
149
149
|
PQclear(this->pgresult);
|
150
|
-
#ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
|
151
150
|
rb_gc_adjust_memory_usage(-this->result_size);
|
152
|
-
#endif
|
153
151
|
}
|
154
152
|
this->result_size = 0;
|
155
153
|
this->nfields = -1;
|
@@ -180,7 +178,7 @@ static const rb_data_type_t pgresult_type = {
|
|
180
178
|
pgresult_gc_mark,
|
181
179
|
pgresult_gc_free,
|
182
180
|
pgresult_memsize,
|
183
|
-
|
181
|
+
pgresult_gc_compact,
|
184
182
|
},
|
185
183
|
0, 0,
|
186
184
|
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
@@ -253,9 +251,7 @@ pg_new_result(PGresult *result, VALUE rb_pgconn)
|
|
253
251
|
*/
|
254
252
|
this->result_size = pgresult_approx_size(result);
|
255
253
|
|
256
|
-
#ifdef HAVE_RB_GC_ADJUST_MEMORY_USAGE
|
257
254
|
rb_gc_adjust_memory_usage(this->result_size);
|
258
|
-
#endif
|
259
255
|
|
260
256
|
return self;
|
261
257
|
}
|
@@ -323,6 +319,9 @@ pg_result_check( VALUE self )
|
|
323
319
|
case PGRES_COMMAND_OK:
|
324
320
|
#ifdef HAVE_PQENTERPIPELINEMODE
|
325
321
|
case PGRES_PIPELINE_SYNC:
|
322
|
+
#endif
|
323
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
324
|
+
case PGRES_TUPLES_CHUNK:
|
326
325
|
#endif
|
327
326
|
return self;
|
328
327
|
case PGRES_BAD_RESPONSE:
|
@@ -549,6 +548,7 @@ static void pgresult_init_fnames(VALUE self)
|
|
549
548
|
* * +PGRES_FATAL_ERROR+
|
550
549
|
* * +PGRES_COPY_BOTH+
|
551
550
|
* * +PGRES_SINGLE_TUPLE+
|
551
|
+
* * +PGRES_TUPLES_CHUNK+
|
552
552
|
* * +PGRES_PIPELINE_SYNC+
|
553
553
|
* * +PGRES_PIPELINE_ABORTED+
|
554
554
|
*
|
@@ -613,14 +613,12 @@ pgresult_error_message(VALUE self)
|
|
613
613
|
return ret;
|
614
614
|
}
|
615
615
|
|
616
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
617
616
|
/*
|
618
617
|
* call-seq:
|
619
618
|
* res.verbose_error_message( verbosity, show_context ) -> String
|
620
619
|
*
|
621
620
|
* Returns a reformatted version of the error message associated with a PGresult object.
|
622
621
|
*
|
623
|
-
* Available since PostgreSQL-9.6
|
624
622
|
*/
|
625
623
|
static VALUE
|
626
624
|
pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
@@ -639,7 +637,6 @@ pgresult_verbose_error_message(VALUE self, VALUE verbosity, VALUE show_context)
|
|
639
637
|
|
640
638
|
return ret;
|
641
639
|
}
|
642
|
-
#endif
|
643
640
|
|
644
641
|
/*
|
645
642
|
* call-seq:
|
@@ -1528,6 +1525,9 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1528
1525
|
return self;
|
1529
1526
|
rb_raise( rb_eInvalidResultStatus, "PG::Result is not in single row mode");
|
1530
1527
|
case PGRES_SINGLE_TUPLE:
|
1528
|
+
#ifdef HAVE_PQSETCHUNKEDROWSMODE
|
1529
|
+
case PGRES_TUPLES_CHUNK:
|
1530
|
+
#endif
|
1531
1531
|
break;
|
1532
1532
|
default:
|
1533
1533
|
pg_result_check( self );
|
@@ -1572,7 +1572,7 @@ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* da
|
|
1572
1572
|
* wrapping each row into a dedicated result object, it delivers data in nearly
|
1573
1573
|
* the same speed as with ordinary results.
|
1574
1574
|
*
|
1575
|
-
* The base result must be in status PGRES_SINGLE_TUPLE.
|
1575
|
+
* The base result must be in status PGRES_SINGLE_TUPLE or PGRES_TUPLES_CHUNK.
|
1576
1576
|
* It iterates over all tuples until the status changes to PGRES_TUPLES_OK.
|
1577
1577
|
* A PG::Error is raised for any errors from the server.
|
1578
1578
|
*
|
@@ -1707,10 +1707,8 @@ init_pg_result(void)
|
|
1707
1707
|
rb_define_singleton_method(rb_cPGresult, "res_status", pgresult_s_res_status, 1);
|
1708
1708
|
rb_define_method(rb_cPGresult, "error_message", pgresult_error_message, 0);
|
1709
1709
|
rb_define_alias( rb_cPGresult, "result_error_message", "error_message");
|
1710
|
-
#ifdef HAVE_PQRESULTVERBOSEERRORMESSAGE
|
1711
1710
|
rb_define_method(rb_cPGresult, "verbose_error_message", pgresult_verbose_error_message, 2);
|
1712
1711
|
rb_define_alias( rb_cPGresult, "result_verbose_error_message", "verbose_error_message");
|
1713
|
-
#endif
|
1714
1712
|
rb_define_method(rb_cPGresult, "error_field", pgresult_error_field, 1);
|
1715
1713
|
rb_define_alias( rb_cPGresult, "result_error_field", "error_field" );
|
1716
1714
|
rb_define_method(rb_cPGresult, "clear", pg_result_clear, 0);
|
data/ext/pg_text_encoder.c
CHANGED
@@ -231,7 +231,7 @@ pg_text_enc_integer(t_pg_coder *this, VALUE value, char *out, VALUE *intermediat
|
|
231
231
|
*
|
232
232
|
*/
|
233
233
|
static int
|
234
|
-
pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *
|
234
|
+
pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate1, int enc_idx)
|
235
235
|
{
|
236
236
|
if(out){
|
237
237
|
double dvalue = NUM2DBL(value);
|
@@ -239,7 +239,6 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
239
239
|
int neg = 0;
|
240
240
|
int exp2i, exp10i, i;
|
241
241
|
unsigned long long ll, remainder, oldval;
|
242
|
-
VALUE intermediate;
|
243
242
|
|
244
243
|
/* Cast to the same strings as value.to_s . */
|
245
244
|
if( isinf(dvalue) ){
|
@@ -283,6 +282,7 @@ pg_text_enc_float(t_pg_coder *conv, VALUE value, char *out, VALUE *intermediate,
|
|
283
282
|
|
284
283
|
if( exp10i <= -5 || exp10i >= 15 ) {
|
285
284
|
/* Write the float in exponent format (1.23e45) */
|
285
|
+
VALUE intermediate;
|
286
286
|
|
287
287
|
/* write fraction digits from right to left */
|
288
288
|
for( i = MAX_DOUBLE_DIGITS; i > 1; i--){
|
data/ext/pg_tuple.c
CHANGED
@@ -125,7 +125,7 @@ static const rb_data_type_t pg_tuple_type = {
|
|
125
125
|
pg_tuple_gc_mark,
|
126
126
|
pg_tuple_gc_free,
|
127
127
|
pg_tuple_memsize,
|
128
|
-
|
128
|
+
pg_tuple_gc_compact,
|
129
129
|
},
|
130
130
|
0, 0,
|
131
131
|
RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | PG_RUBY_TYPED_FROZEN_SHAREABLE,
|
@@ -135,7 +135,7 @@ static const rb_data_type_t pg_tuple_type = {
|
|
135
135
|
* Document-method: allocate
|
136
136
|
*
|
137
137
|
* call-seq:
|
138
|
-
* PG::
|
138
|
+
* PG::Tuple.allocate -> obj
|
139
139
|
*/
|
140
140
|
static VALUE
|
141
141
|
pg_tuple_s_allocate( VALUE klass )
|
data/ext/pg_type_map.c
CHANGED
data/ext/pg_type_map_by_class.c
CHANGED
data/ext/pg_type_map_by_column.c
CHANGED
data/ext/pg_type_map_by_oid.c
CHANGED
data/ext/pg_type_map_in_ruby.c
CHANGED
data/lib/2.7/pg_ext.so
CHANGED
Binary file
|
data/lib/3.0/pg_ext.so
CHANGED
Binary file
|
@@ -127,8 +127,8 @@ class PG::BasicTypeRegistry
|
|
127
127
|
@maps = [
|
128
128
|
[0, :encoder, PG::TextEncoder::Array],
|
129
129
|
[0, :decoder, PG::TextDecoder::Array],
|
130
|
-
[1, :encoder,
|
131
|
-
[1, :decoder,
|
130
|
+
[1, :encoder, PG::BinaryEncoder::Array],
|
131
|
+
[1, :decoder, PG::BinaryDecoder::Array],
|
132
132
|
].inject([]) do |h, (format, direction, arraycoder)|
|
133
133
|
coders = registry.coders_for(format, direction) || {}
|
134
134
|
h[format] ||= {}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pg' unless defined?( PG )
|
5
|
+
|
6
|
+
if defined?(PG::CancelConnection)
|
7
|
+
class PG::CancelConnection
|
8
|
+
include PG::Connection::Pollable
|
9
|
+
|
10
|
+
# The timeout used by #cancel and async_cancel to establish the cancel connection.
|
11
|
+
attr_accessor :async_connect_timeout
|
12
|
+
|
13
|
+
# call-seq:
|
14
|
+
# conn.cancel
|
15
|
+
#
|
16
|
+
# Requests that the server abandons processing of the current command in a blocking manner.
|
17
|
+
#
|
18
|
+
# If the cancel request wasn't successfully dispatched an error message is raised.
|
19
|
+
#
|
20
|
+
# Successful dispatch of the cancellation is no guarantee that the request will have any effect, however.
|
21
|
+
# If the cancellation is effective, the command being canceled will terminate early and raises an error.
|
22
|
+
# If the cancellation fails (say, because the server was already done processing the command), then there will be no visible result at all.
|
23
|
+
#
|
24
|
+
def cancel
|
25
|
+
start
|
26
|
+
polling_loop(:poll, async_connect_timeout)
|
27
|
+
end
|
28
|
+
alias async_cancel cancel
|
29
|
+
end
|
30
|
+
end
|
data/lib/pg/connection.rb
CHANGED
@@ -356,21 +356,18 @@ class PG::Connection
|
|
356
356
|
end
|
357
357
|
end
|
358
358
|
|
359
|
-
#
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
ssl_attribute_names.each.with_object({}) do |n,h|
|
372
|
-
h[n] = ssl_attribute(n)
|
373
|
-
end
|
359
|
+
# call-seq:
|
360
|
+
# conn.ssl_attributes -> Hash<String,String>
|
361
|
+
#
|
362
|
+
# Returns SSL-related information about the connection as key/value pairs
|
363
|
+
#
|
364
|
+
# The available attributes varies depending on the SSL library being used,
|
365
|
+
# and the type of connection.
|
366
|
+
#
|
367
|
+
# See also #ssl_attribute
|
368
|
+
def ssl_attributes
|
369
|
+
ssl_attribute_names.each.with_object({}) do |n,h|
|
370
|
+
h[n] = ssl_attribute(n)
|
374
371
|
end
|
375
372
|
end
|
376
373
|
|
@@ -539,6 +536,25 @@ class PG::Connection
|
|
539
536
|
end
|
540
537
|
alias async_put_copy_end put_copy_end
|
541
538
|
|
539
|
+
if method_defined? :send_pipeline_sync
|
540
|
+
# call-seq:
|
541
|
+
# conn.pipeline_sync
|
542
|
+
#
|
543
|
+
# Marks a synchronization point in a pipeline by sending a sync message and flushing the send buffer.
|
544
|
+
# This serves as the delimiter of an implicit transaction and an error recovery point.
|
545
|
+
#
|
546
|
+
# See enter_pipeline_mode
|
547
|
+
#
|
548
|
+
# Raises PG::Error if the connection is not in pipeline mode or sending a sync message failed.
|
549
|
+
#
|
550
|
+
# Available since PostgreSQL-14
|
551
|
+
def pipeline_sync(*args)
|
552
|
+
send_pipeline_sync(*args)
|
553
|
+
flush
|
554
|
+
end
|
555
|
+
alias async_pipeline_sync pipeline_sync
|
556
|
+
end
|
557
|
+
|
542
558
|
if method_defined? :sync_encrypt_password
|
543
559
|
# call-seq:
|
544
560
|
# conn.encrypt_password( password, username, algorithm=nil ) -> String
|
@@ -586,128 +602,144 @@ class PG::Connection
|
|
586
602
|
end
|
587
603
|
alias async_reset reset
|
588
604
|
|
589
|
-
|
590
|
-
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
618
|
-
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
cl.
|
605
|
+
if defined?(PG::CancelConnection)
|
606
|
+
# PostgreSQL-17+
|
607
|
+
|
608
|
+
def sync_cancel
|
609
|
+
cancon = PG::CancelConnection.new(self)
|
610
|
+
cancon.sync_cancel
|
611
|
+
rescue PG::Error => err
|
612
|
+
err.to_s
|
613
|
+
end
|
614
|
+
|
615
|
+
# call-seq:
|
616
|
+
# conn.cancel() -> String
|
617
|
+
#
|
618
|
+
# Requests cancellation of the command currently being
|
619
|
+
# processed.
|
620
|
+
#
|
621
|
+
# Returns +nil+ on success, or a string containing the
|
622
|
+
# error message if a failure occurs.
|
623
|
+
#
|
624
|
+
# On PostgreSQL-17+ client libaray the class PG::CancelConnection is used.
|
625
|
+
# On older client library a pure ruby implementation is used.
|
626
|
+
def cancel
|
627
|
+
cancon = PG::CancelConnection.new(self)
|
628
|
+
cancon.async_connect_timeout = conninfo_hash[:connect_timeout]
|
629
|
+
cancon.async_cancel
|
630
|
+
rescue PG::Error => err
|
631
|
+
err.to_s
|
632
|
+
end
|
633
|
+
|
634
|
+
else
|
635
|
+
|
636
|
+
# PostgreSQL < 17
|
637
|
+
|
638
|
+
def cancel
|
639
|
+
be_pid = backend_pid
|
640
|
+
be_key = backend_key
|
641
|
+
cancel_request = [0x10, 1234, 5678, be_pid, be_key].pack("NnnNN")
|
642
|
+
|
643
|
+
if Fiber.respond_to?(:scheduler) && Fiber.scheduler && RUBY_PLATFORM =~ /mingw|mswin/
|
644
|
+
# Ruby's nonblocking IO is not really supported on Windows.
|
645
|
+
# We work around by using threads and explicit calls to wait_readable/wait_writable.
|
646
|
+
cl = Thread.new(socket_io.remote_address) { |ra| ra.connect }.value
|
647
|
+
begin
|
648
|
+
cl.write_nonblock(cancel_request)
|
649
|
+
rescue IO::WaitReadable, Errno::EINTR
|
650
|
+
cl.wait_writable
|
651
|
+
retry
|
633
652
|
end
|
653
|
+
begin
|
654
|
+
cl.read_nonblock(1)
|
655
|
+
rescue IO::WaitReadable, Errno::EINTR
|
656
|
+
cl.wait_readable
|
657
|
+
retry
|
658
|
+
rescue EOFError
|
659
|
+
end
|
660
|
+
else
|
661
|
+
cl = socket_io.remote_address.connect
|
662
|
+
# Send CANCEL_REQUEST_CODE and parameters
|
663
|
+
cl.write(cancel_request)
|
664
|
+
# Wait for the postmaster to close the connection, which indicates that it's processed the request.
|
665
|
+
cl.read(1)
|
634
666
|
end
|
635
|
-
cl.write(cancel_request)
|
636
|
-
cl.read(1)
|
637
|
-
else
|
638
|
-
cl = socket_io.remote_address.connect
|
639
|
-
# Send CANCEL_REQUEST_CODE and parameters
|
640
|
-
cl.write(cancel_request)
|
641
|
-
# Wait for the postmaster to close the connection, which indicates that it's processed the request.
|
642
|
-
cl.read(1)
|
643
|
-
end
|
644
667
|
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
668
|
+
cl.close
|
669
|
+
nil
|
670
|
+
rescue SystemCallError => err
|
671
|
+
err.to_s
|
672
|
+
end
|
649
673
|
end
|
650
674
|
alias async_cancel cancel
|
651
675
|
|
652
|
-
|
676
|
+
module Pollable
|
653
677
|
# Track the progress of the connection, waiting for the socket to become readable/writable before polling it
|
678
|
+
private def polling_loop(poll_meth, connect_timeout)
|
679
|
+
if (timeo = connect_timeout.to_i) && timeo > 0
|
680
|
+
host_count = conninfo_hash[:host].to_s.count(",") + 1
|
681
|
+
stop_time = timeo * host_count + Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
682
|
+
end
|
654
683
|
|
655
|
-
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
IO
|
684
|
+
poll_status = PG::PGRES_POLLING_WRITING
|
685
|
+
until poll_status == PG::PGRES_POLLING_OK ||
|
686
|
+
poll_status == PG::PGRES_POLLING_FAILED
|
687
|
+
|
688
|
+
# Set single timeout to parameter "connect_timeout" but
|
689
|
+
# don't exceed total connection time of number-of-hosts * connect_timeout.
|
690
|
+
timeout = [timeo, stop_time - Process.clock_gettime(Process::CLOCK_MONOTONIC)].min if stop_time
|
691
|
+
event = if !timeout || timeout >= 0
|
692
|
+
# If the socket needs to read, wait 'til it becomes readable to poll again
|
693
|
+
case poll_status
|
694
|
+
when PG::PGRES_POLLING_READING
|
695
|
+
if defined?(IO::READABLE) # ruby-3.0+
|
696
|
+
socket_io.wait(IO::READABLE | IO::PRIORITY, timeout)
|
697
|
+
else
|
698
|
+
IO.select([socket_io], nil, [socket_io], timeout)
|
699
|
+
end
|
700
|
+
|
701
|
+
# ...and the same for when the socket needs to write
|
702
|
+
when PG::PGRES_POLLING_WRITING
|
703
|
+
if defined?(IO::WRITABLE) # ruby-3.0+
|
704
|
+
# Use wait instead of wait_readable, since connection errors are delivered as
|
705
|
+
# exceptional/priority events on Windows.
|
706
|
+
socket_io.wait(IO::WRITABLE | IO::PRIORITY, timeout)
|
707
|
+
else
|
708
|
+
# io#wait on ruby-2.x doesn't wait for priority, so fallback to IO.select
|
709
|
+
IO.select(nil, [socket_io], [socket_io], timeout)
|
710
|
+
end
|
675
711
|
end
|
676
|
-
|
677
|
-
#
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
712
|
+
end
|
713
|
+
# connection to server at "localhost" (127.0.0.1), port 5433 failed: timeout expired (PG::ConnectionBad)
|
714
|
+
# connection to server on socket "/var/run/postgresql/.s.PGSQL.5433" failed: No such file or directory
|
715
|
+
unless event
|
716
|
+
if self.class.send(:host_is_named_pipe?, host)
|
717
|
+
connhost = "on socket \"#{host}\""
|
718
|
+
elsif respond_to?(:hostaddr)
|
719
|
+
connhost = "at \"#{host}\" (#{hostaddr}), port #{port}"
|
683
720
|
else
|
684
|
-
|
685
|
-
IO.select(nil, [socket_io], [socket_io], timeout)
|
721
|
+
connhost = "at \"#{host}\", port #{port}"
|
686
722
|
end
|
723
|
+
raise PG::ConnectionBad.new("connection to server #{connhost} failed: timeout expired", connection: self)
|
687
724
|
end
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
unless event
|
692
|
-
if self.class.send(:host_is_named_pipe?, host)
|
693
|
-
connhost = "on socket \"#{host}\""
|
694
|
-
elsif respond_to?(:hostaddr)
|
695
|
-
connhost = "at \"#{host}\" (#{hostaddr}), port #{port}"
|
696
|
-
else
|
697
|
-
connhost = "at \"#{host}\", port #{port}"
|
698
|
-
end
|
699
|
-
raise PG::ConnectionBad.new("connection to server #{connhost} failed: timeout expired", connection: self)
|
725
|
+
|
726
|
+
# Check to see if it's finished or failed yet
|
727
|
+
poll_status = send( poll_meth )
|
700
728
|
end
|
701
729
|
|
702
|
-
|
703
|
-
|
730
|
+
unless status == PG::CONNECTION_OK
|
731
|
+
msg = error_message
|
732
|
+
finish
|
733
|
+
raise PG::ConnectionBad.new(msg, connection: self)
|
734
|
+
end
|
704
735
|
end
|
736
|
+
end
|
705
737
|
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
710
|
-
|
738
|
+
include Pollable
|
739
|
+
|
740
|
+
private def async_connect_or_reset(poll_meth)
|
741
|
+
# Track the progress of the connection, waiting for the socket to become readable/writable before polling it
|
742
|
+
polling_loop(poll_meth, conninfo_hash[:connect_timeout])
|
711
743
|
|
712
744
|
# Set connection to nonblocking to handle all blocking states in ruby.
|
713
745
|
# That way a fiber scheduler is able to handle IO requests.
|
@@ -825,6 +857,14 @@ class PG::Connection
|
|
825
857
|
iopts = PG::Connection.conninfo_parse(option_string).each_with_object({}){|h, o| o[h[:keyword].to_sym] = h[:val] if h[:val] }
|
826
858
|
iopts = PG::Connection.conndefaults.each_with_object({}){|h, o| o[h[:keyword].to_sym] = h[:val] if h[:val] }.merge(iopts)
|
827
859
|
|
860
|
+
if PG::BUNDLED_LIBPQ_WITH_UNIXSOCKET && iopts[:host].to_s.empty?
|
861
|
+
# Many distors patch the hardcoded default UnixSocket path in libpq to /var/run/postgresql instead of /tmp .
|
862
|
+
# We simply try them all.
|
863
|
+
iopts[:host] = "/var/run/postgresql" + # Ubuntu, Debian, Fedora, Opensuse
|
864
|
+
",/run/postgresql" + # Alpine, Archlinux, Gentoo
|
865
|
+
",/tmp" # Stock PostgreSQL
|
866
|
+
end
|
867
|
+
|
828
868
|
iopts_for_reset = iopts
|
829
869
|
if iopts[:hostaddr]
|
830
870
|
# hostaddr is provided -> no need to resolve hostnames
|
@@ -897,14 +937,29 @@ class PG::Connection
|
|
897
937
|
private_constant :REDIRECT_CLASS_METHODS
|
898
938
|
|
899
939
|
# These methods are affected by PQsetnonblocking
|
900
|
-
REDIRECT_SEND_METHODS =
|
940
|
+
REDIRECT_SEND_METHODS = {
|
901
941
|
:isnonblocking => [:async_isnonblocking, :sync_isnonblocking],
|
902
942
|
:nonblocking? => [:async_isnonblocking, :sync_isnonblocking],
|
903
943
|
:put_copy_data => [:async_put_copy_data, :sync_put_copy_data],
|
904
944
|
:put_copy_end => [:async_put_copy_end, :sync_put_copy_end],
|
905
945
|
:flush => [:async_flush, :sync_flush],
|
906
|
-
}
|
946
|
+
}
|
907
947
|
private_constant :REDIRECT_SEND_METHODS
|
948
|
+
if PG::Connection.instance_methods.include? :sync_pipeline_sync
|
949
|
+
if PG::Connection.instance_methods.include? :send_pipeline_sync
|
950
|
+
# PostgreSQL-17+
|
951
|
+
REDIRECT_SEND_METHODS.merge!({
|
952
|
+
:pipeline_sync => [:async_pipeline_sync, :sync_pipeline_sync],
|
953
|
+
})
|
954
|
+
else
|
955
|
+
# PostgreSQL-14+
|
956
|
+
REDIRECT_SEND_METHODS.merge!({
|
957
|
+
:pipeline_sync => [:sync_pipeline_sync, :sync_pipeline_sync],
|
958
|
+
})
|
959
|
+
end
|
960
|
+
end
|
961
|
+
PG.make_shareable(REDIRECT_SEND_METHODS)
|
962
|
+
|
908
963
|
REDIRECT_METHODS = {
|
909
964
|
:exec => [:async_exec, :sync_exec],
|
910
965
|
:query => [:async_exec, :sync_exec],
|
@@ -921,12 +976,13 @@ class PG::Connection
|
|
921
976
|
:set_client_encoding => [:async_set_client_encoding, :sync_set_client_encoding],
|
922
977
|
:client_encoding= => [:async_set_client_encoding, :sync_set_client_encoding],
|
923
978
|
:cancel => [:async_cancel, :sync_cancel],
|
979
|
+
:encrypt_password => [:async_encrypt_password, :sync_encrypt_password],
|
924
980
|
}
|
925
981
|
private_constant :REDIRECT_METHODS
|
926
|
-
|
927
|
-
if PG::Connection.instance_methods.include? :async_encrypt_password
|
982
|
+
if PG::Connection.instance_methods.include? :async_close_prepared
|
928
983
|
REDIRECT_METHODS.merge!({
|
929
|
-
:
|
984
|
+
:close_prepared => [:async_close_prepared, :sync_close_prepared],
|
985
|
+
:close_portal => [:async_close_portal, :sync_close_portal],
|
930
986
|
})
|
931
987
|
end
|
932
988
|
PG.make_shareable(REDIRECT_METHODS)
|