pg 1.4.3 → 1.4.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4978742f10cf7b28bae9bb25698563f13a116bbf2aebd503063dd28f2b3e128b
4
- data.tar.gz: '076801209c5d5e3f49e7bebe46a2bf86c806d8150313a0248649942b81b932bc'
3
+ metadata.gz: 7796bdf07cbb37a4b63c29b24e18e312682eca28a98042ce7e050c99b6fa6b98
4
+ data.tar.gz: 4c2e99d5a102f695f82f3f0fe626a63eff42a416fc1db99175aa3dbecac0e010
5
5
  SHA512:
6
- metadata.gz: c9e28051c8929433b47b41aaf1fbabf2b708f28044307b66d133da0f6fc2192582a7dda52e4b23ffc9cf2d22bec0a5c7456265331ba1a885828eac99496e0d6d
7
- data.tar.gz: e5a99bb04b80c6dc2628c72f79b6ce07aa1f15b10dc53ab71f1a5d667bf349171e31611c6217075f3475d611e905db4103f3f5553f2b9bf9a576d857b346f1f2
6
+ metadata.gz: ef67ef88819cf75dd74b8f15843b44a45dfe580bb8c51a632cef5a38c00b519cb81c0a84191fd94e281cb7e8264ebc31a32b9ad51b7e7e9c17e514fcf5f023e0
7
+ data.tar.gz: 3bec55fa8e3a23dcef29673566f5c0570be43e319af84838625fcfe87aa81ff8e9b7ab9c1bed6ae6c28097d93a6675dd3ee5b03c9ece601f87be90e2d885ca75
checksums.yaml.gz.sig CHANGED
@@ -1,3 +1 @@
1
- ?�� hSẃ�5r��'p�*�\V�����c4^��f�<����u��S��b��*\�Ԟ�$l��sC��l$ĬD9�.M듹����* d���Mf��D �������k��p=�FM�
2
- �� ���曏A�U^Л�9'��N�@}x�Jv
3
- =2C�W7�sG�@���4�X�{��BQ��6-��b�-Q�V� y�P�������k�[�<!���'�͢�6e;b��6�R�G�y+�\�}����x�>_�_��>�J ��z�僕�[ц]��R���fW&Z%s���#��%:@�X'�!k��[$�z.�,8��FB50U y���w�+T-)ۑ�곛q*%�q0AS�{�\p���b*�
1
+ }�"�����B�`�5�'˟���1��d�x�;� �Y�=�r4S�y��Z��3��R$Z2�� V7O@�����m6�%���P��ُ~���0{����hꉖ4� D�:��`�4�eb��ݫ%���e'4�ܓ�X�E�%$k���n� .�Yw#���� ���-|#@n=���^�V�bI>����Ŕ���o*l�O�5���UU�chR��飹�+�I��G��ڼ���'6Z�$#�_1W��Ah3
@@ -45,7 +45,7 @@ jobs:
45
45
  include:
46
46
  - ruby: "3.1"
47
47
  platform: "x64-mingw-ucrt"
48
- PGVERSION: 14.2-1-windows-x64
48
+ PGVERSION: 15.0-rc1-windows-x64
49
49
  - ruby: "2.5"
50
50
  platform: "x64-mingw32"
51
51
  PGVERSION: 10.20-1-windows
@@ -83,4 +83,4 @@ jobs:
83
83
  - run: bundle install
84
84
  - run: gem install --local pg-*${{ matrix.platform }}.gem --verbose
85
85
  - name: Run specs
86
- run: ruby -rpg -S rspec spec/**/*_spec.rb
86
+ run: ruby -rpg -S rspec -fd spec/**/*_spec.rb
@@ -31,7 +31,7 @@ jobs:
31
31
  include:
32
32
  - os: windows
33
33
  ruby: "head"
34
- PGVERSION: 14.2-1-windows-x64
34
+ PGVERSION: 15.0-rc1-windows-x64
35
35
  PGVER: "14"
36
36
  - os: windows
37
37
  ruby: "2.5"
@@ -54,13 +54,14 @@ jobs:
54
54
  PGVER: "14"
55
55
  - os: macos
56
56
  ruby: "head"
57
- PGVERSION: 14.2-1-osx
58
- PGVER: "14"
57
+ PGVERSION: 13.8-1-osx
58
+ PGVER: "13"
59
59
 
60
60
  runs-on: ${{ matrix.os }}-latest
61
61
  env:
62
62
  PGVERSION: ${{ matrix.PGVERSION }}
63
63
  PGVER: ${{ matrix.PGVER }}
64
+ MAKE: make -j2 V=1
64
65
 
65
66
  steps:
66
67
  - uses: actions/checkout@v2
@@ -107,8 +108,9 @@ jobs:
107
108
  if: matrix.os == 'macos'
108
109
  run: |
109
110
  wget https://get.enterprisedb.com/postgresql/postgresql-$PGVERSION-binaries.zip && \
110
- unzip postgresql-$PGVERSION-binaries.zip && \
111
- echo `pwd`/pgsql/bin >> $GITHUB_PATH
111
+ sudo mkdir -p /Library/PostgreSQL && \
112
+ sudo unzip postgresql-$PGVERSION-binaries.zip -d /Library/PostgreSQL/$PGVER && \
113
+ echo /Library/PostgreSQL/$PGVER/bin >> $GITHUB_PATH
112
114
 
113
115
  - run: gem update --system
114
116
  - run: bundle install
data/History.rdoc CHANGED
@@ -1,3 +1,13 @@
1
+ == v1.4.4 [2022-10-11] Lars Kanis <lars@greiz-reinsdorf.de>
2
+
3
+ - Revert to let libpq do the host iteration while connecting. #485
4
+ Ensure that parameter `connect_timeout` is still respected.
5
+ - Handle multiple hosts in the connection string, where only one host has writable session. #476
6
+ - Add some useful information to PG::Connection#inspect. #487
7
+ - Support new pgresult_stream_any API in sequel_pg-1.17.0. #481
8
+ - Update Windows fat binary gem to PostgreSQL-14.5.
9
+
10
+
1
11
  == v1.4.3 [2022-08-09] Lars Kanis <lars@greiz-reinsdorf.de>
2
12
 
3
13
  - Avoid memory bloat possible in put_copy_data in pg-1.4.0 to 1.4.2. #473
data/README.rdoc CHANGED
@@ -171,12 +171,31 @@ The following type maps are prefilled with type mappings from the PG::BasicTypeR
171
171
  To report bugs, suggest features, or check out the source with Git,
172
172
  {check out the project page}[https://github.com/ged/ruby-pg].
173
173
 
174
- After checking out the source, run:
174
+ After checking out the source, install all dependencies:
175
175
 
176
- $ rake newb
176
+ $ bundle install
177
177
 
178
- This task will install any missing dependencies, run the tests/specs, and
179
- generate the API documentation.
178
+ Cleanup extension files, packaging files, test databases:
179
+
180
+ $ rake clean
181
+
182
+ Compile extension:
183
+
184
+ $ rake compile
185
+
186
+ Run tests/specs with PostgreSQL tools like `initdb` in the path:
187
+
188
+ $ PATH=$PATH:/usr/lib/postgresql/14/bin rake test
189
+
190
+ Or run a specific test with the line number:
191
+
192
+ $ PATH=$PATH:/usr/lib/postgresql/14/bin rspec -Ilib -fd spec/pg/connection_spec.rb:455
193
+
194
+ Generate the API documentation:
195
+
196
+ $ rake docs
197
+
198
+ Make sure, that all bugs and new features are verified by tests.
180
199
 
181
200
  The current maintainers are Michael Granger <ged@FaerieMUD.org> and
182
201
  Lars Kanis <lars@greiz-reinsdorf.de>.
@@ -184,7 +203,7 @@ Lars Kanis <lars@greiz-reinsdorf.de>.
184
203
 
185
204
  == Copying
186
205
 
187
- Copyright (c) 1997-2019 by the authors.
206
+ Copyright (c) 1997-2022 by the authors.
188
207
 
189
208
  * Jeff Davis <ruby-pg@j-davis.com>
190
209
  * Guy Decoux (ts) <decoux@moulon.inra.fr>
data/Rakefile CHANGED
@@ -16,14 +16,14 @@ LIBDIR = BASEDIR + 'lib'
16
16
  EXTDIR = BASEDIR + 'ext'
17
17
  PKGDIR = BASEDIR + 'pkg'
18
18
  TMPDIR = BASEDIR + 'tmp'
19
- TESTDIR = BASEDIR + "tmp_test_specs"
19
+ TESTDIR = BASEDIR + "tmp_test_*"
20
20
 
21
21
  DLEXT = RbConfig::CONFIG['DLEXT']
22
22
  EXT = LIBDIR + "pg_ext.#{DLEXT}"
23
23
 
24
24
  GEMSPEC = 'pg.gemspec'
25
25
 
26
- CLOBBER.include( TESTDIR.to_s )
26
+ CLEAN.include( TESTDIR.to_s )
27
27
  CLEAN.include( PKGDIR.to_s, TMPDIR.to_s )
28
28
  CLEAN.include "lib/*/libpq.dll"
29
29
  CLEAN.include "lib/pg_ext.*"
data/Rakefile.cross CHANGED
@@ -32,7 +32,7 @@ class CrossLibrary < OpenStruct
32
32
 
33
33
  # Cross-compilation constants
34
34
  self.openssl_version = ENV['OPENSSL_VERSION'] || '1.1.1q'
35
- self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '14.4'
35
+ self.postgresql_version = ENV['POSTGRESQL_VERSION'] || '14.5'
36
36
 
37
37
  # Check if symlinks work in the current working directory.
38
38
  # This fails, if rake-compiler-dock is running on a Windows box.
data/ext/pg.c CHANGED
@@ -47,7 +47,6 @@
47
47
  */
48
48
 
49
49
  #include "pg.h"
50
- #include "pg_config.h"
51
50
 
52
51
  int pg_skip_deprecation_warning;
53
52
  VALUE rb_mPG;
@@ -353,7 +352,7 @@ pg_s_init_ssl(VALUE self, VALUE do_ssl)
353
352
  **************************************************************************/
354
353
 
355
354
  void
356
- Init_pg_ext()
355
+ Init_pg_ext(void)
357
356
  {
358
357
  if( RTEST(rb_eval_string("ENV['PG_SKIP_DEPRECATION_WARNING']")) ){
359
358
  /* Set all bits to disable all deprecation warnings. */
data/ext/pg.h CHANGED
@@ -57,6 +57,7 @@
57
57
  #endif
58
58
 
59
59
  /* PostgreSQL headers */
60
+ #include "pg_config.h"
60
61
  #include "libpq-fe.h"
61
62
  #include "libpq/libpq-fs.h" /* large-object interface */
62
63
  #include "pg_config_manual.h"
@@ -205,7 +205,7 @@ pg_bin_dec_timestamp(t_pg_coder *conv, const char *val, int len, int tuple, int
205
205
  */
206
206
 
207
207
  void
208
- init_pg_binary_decoder()
208
+ init_pg_binary_decoder(void)
209
209
  {
210
210
  /* This module encapsulates all decoder classes with binary input format */
211
211
  rb_mPG_BinaryDecoder = rb_define_module_under( rb_mPG, "BinaryDecoder" );
@@ -139,7 +139,7 @@ pg_bin_enc_from_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermed
139
139
  }
140
140
 
141
141
  void
142
- init_pg_binary_encoder()
142
+ init_pg_binary_encoder(void)
143
143
  {
144
144
  /* This module encapsulates all encoder classes with binary output format */
145
145
  rb_mPG_BinaryEncoder = rb_define_module_under( rb_mPG, "BinaryEncoder" );
data/ext/pg_coder.c CHANGED
@@ -537,7 +537,7 @@ pg_coder_dec_func(t_pg_coder *this, int binary)
537
537
 
538
538
 
539
539
  void
540
- init_pg_coder()
540
+ init_pg_coder(void)
541
541
  {
542
542
  s_id_encode = rb_intern("encode");
543
543
  s_id_decode = rb_intern("decode");
data/ext/pg_connection.c CHANGED
@@ -1527,8 +1527,7 @@ pgconn_sync_describe_prepared(VALUE self, VALUE stmt_name)
1527
1527
  * It's not recommended to use explicit sync or async variants but #describe_portal instead, unless you have a good reason to do so.
1528
1528
  */
1529
1529
  static VALUE
1530
- pgconn_sync_describe_portal(self, stmt_name)
1531
- VALUE self, stmt_name;
1530
+ pgconn_sync_describe_portal(VALUE self, VALUE stmt_name)
1532
1531
  {
1533
1532
  PGresult *result;
1534
1533
  VALUE rb_pgresult;
@@ -4326,7 +4325,7 @@ pgconn_field_name_type_get(VALUE self)
4326
4325
  * Document-class: PG::Connection
4327
4326
  */
4328
4327
  void
4329
- init_pg_connection()
4328
+ init_pg_connection(void)
4330
4329
  {
4331
4330
  s_id_encode = rb_intern("encode");
4332
4331
  s_id_autoclose_set = rb_intern("autoclose=");
data/ext/pg_copy_coder.c CHANGED
@@ -592,7 +592,7 @@ pg_text_dec_copy_row(t_pg_coder *conv, const char *input_line, int len, int _tup
592
592
 
593
593
 
594
594
  void
595
- init_pg_copycoder()
595
+ init_pg_copycoder(void)
596
596
  {
597
597
  /* Document-class: PG::CopyCoder < PG::Coder
598
598
  *
data/ext/pg_errors.c CHANGED
@@ -70,7 +70,7 @@ lookup_error_class(const char *sqlstate)
70
70
  }
71
71
 
72
72
  void
73
- init_pg_errors()
73
+ init_pg_errors(void)
74
74
  {
75
75
  rb_hErrors = rb_hash_new();
76
76
  rb_define_const( rb_mPG, "ERROR_CLASSES", rb_hErrors );
@@ -494,7 +494,7 @@ pg_text_dec_record(t_pg_coder *conv, char *input_line, int len, int _tuple, int
494
494
 
495
495
 
496
496
  void
497
- init_pg_recordcoder()
497
+ init_pg_recordcoder(void)
498
498
  {
499
499
  /* Document-class: PG::RecordCoder < PG::Coder
500
500
  *
data/ext/pg_result.c CHANGED
@@ -1382,21 +1382,20 @@ pgresult_type_map_get(VALUE self)
1382
1382
  }
1383
1383
 
1384
1384
 
1385
- static void
1385
+ static int
1386
1386
  yield_hash(VALUE self, int ntuples, int nfields, void *data)
1387
1387
  {
1388
1388
  int tuple_num;
1389
- t_pg_result *this = pgresult_get_this(self);
1390
1389
  UNUSED(nfields);
1391
1390
 
1392
1391
  for(tuple_num = 0; tuple_num < ntuples; tuple_num++) {
1393
1392
  rb_yield(pgresult_aref(self, INT2NUM(tuple_num)));
1394
1393
  }
1395
1394
 
1396
- pgresult_clear( this );
1395
+ return 1; /* clear the result */
1397
1396
  }
1398
1397
 
1399
- static void
1398
+ static int
1400
1399
  yield_array(VALUE self, int ntuples, int nfields, void *data)
1401
1400
  {
1402
1401
  int row;
@@ -1413,10 +1412,10 @@ yield_array(VALUE self, int ntuples, int nfields, void *data)
1413
1412
  rb_yield( rb_ary_new4( nfields, row_values ));
1414
1413
  }
1415
1414
 
1416
- pgresult_clear( this );
1415
+ return 1; /* clear the result */
1417
1416
  }
1418
1417
 
1419
- static void
1418
+ static int
1420
1419
  yield_tuple(VALUE self, int ntuples, int nfields, void *data)
1421
1420
  {
1422
1421
  int tuple_num;
@@ -1434,11 +1433,12 @@ yield_tuple(VALUE self, int ntuples, int nfields, void *data)
1434
1433
  VALUE tuple = pgresult_tuple(copy, INT2FIX(tuple_num));
1435
1434
  rb_yield( tuple );
1436
1435
  }
1436
+ return 0; /* don't clear the result */
1437
1437
  }
1438
1438
 
1439
1439
  /* Non-static, and data pointer for use by sequel_pg */
1440
1440
  VALUE
1441
- pgresult_stream_any(VALUE self, void (*yielder)(VALUE, int, int, void*), void* data)
1441
+ pgresult_stream_any(VALUE self, int (*yielder)(VALUE, int, int, void*), void* data)
1442
1442
  {
1443
1443
  t_pg_result *this;
1444
1444
  int nfields;
@@ -1467,7 +1467,9 @@ pgresult_stream_any(VALUE self, void (*yielder)(VALUE, int, int, void*), void* d
1467
1467
  pg_result_check( self );
1468
1468
  }
1469
1469
 
1470
- yielder( self, ntuples, nfields, data );
1470
+ if( yielder( self, ntuples, nfields, data ) ){
1471
+ pgresult_clear( this );
1472
+ }
1471
1473
 
1472
1474
  if( gvl_PQisBusy(pgconn) ){
1473
1475
  /* wait for input (without blocking) before reading each result */
@@ -1617,7 +1619,7 @@ pgresult_field_name_type_get(VALUE self)
1617
1619
  }
1618
1620
 
1619
1621
  void
1620
- init_pg_result()
1622
+ init_pg_result(void)
1621
1623
  {
1622
1624
  sym_string = ID2SYM(rb_intern("string"));
1623
1625
  sym_symbol = ID2SYM(rb_intern("symbol"));
@@ -923,7 +923,7 @@ pg_text_dec_inet(t_pg_coder *conv, const char *val, int len, int tuple, int fiel
923
923
  }
924
924
 
925
925
  void
926
- init_pg_text_decoder()
926
+ init_pg_text_decoder(void)
927
927
  {
928
928
  rb_require("ipaddr");
929
929
  s_IPAddr = rb_funcall(rb_cObject, rb_intern("const_get"), 1, rb_str_new2("IPAddr"));
@@ -775,7 +775,7 @@ pg_text_enc_to_base64(t_pg_coder *conv, VALUE value, char *out, VALUE *intermedi
775
775
 
776
776
 
777
777
  void
778
- init_pg_text_encoder()
778
+ init_pg_text_encoder(void)
779
779
  {
780
780
  s_id_encode = rb_intern("encode");
781
781
  s_id_to_i = rb_intern("to_i");
data/ext/pg_tuple.c CHANGED
@@ -545,7 +545,7 @@ pg_tuple_load(VALUE self, VALUE a)
545
545
  }
546
546
 
547
547
  void
548
- init_pg_tuple()
548
+ init_pg_tuple(void)
549
549
  {
550
550
  rb_cPG_Tuple = rb_define_class_under( rb_mPG, "Tuple", rb_cObject );
551
551
  rb_define_alloc_func( rb_cPG_Tuple, pg_tuple_s_allocate );
data/ext/pg_type_map.c CHANGED
@@ -176,7 +176,7 @@ pg_typemap_with_default_type_map(VALUE self, VALUE typemap)
176
176
  }
177
177
 
178
178
  void
179
- init_pg_type_map()
179
+ init_pg_type_map(void)
180
180
  {
181
181
  s_id_fit_to_query = rb_intern("fit_to_query");
182
182
  s_id_fit_to_result = rb_intern("fit_to_result");
@@ -105,7 +105,7 @@ pg_tmas_s_allocate( VALUE klass )
105
105
 
106
106
 
107
107
  void
108
- init_pg_type_map_all_strings()
108
+ init_pg_type_map_all_strings(void)
109
109
  {
110
110
  /*
111
111
  * Document-class: PG::TypeMapAllStrings < PG::TypeMap
@@ -247,7 +247,7 @@ pg_tmbk_coders( VALUE self )
247
247
  }
248
248
 
249
249
  void
250
- init_pg_type_map_by_class()
250
+ init_pg_type_map_by_class(void)
251
251
  {
252
252
  /*
253
253
  * Document-class: PG::TypeMapByClass < PG::TypeMap
@@ -243,7 +243,7 @@ pg_tmbc_s_allocate( VALUE klass )
243
243
  }
244
244
 
245
245
  VALUE
246
- pg_tmbc_allocate()
246
+ pg_tmbc_allocate(void)
247
247
  {
248
248
  return pg_tmbc_s_allocate(rb_cTypeMapByColumn);
249
249
  }
@@ -320,7 +320,7 @@ pg_tmbc_coders(VALUE self)
320
320
  }
321
321
 
322
322
  void
323
- init_pg_type_map_by_column()
323
+ init_pg_type_map_by_column(void)
324
324
  {
325
325
  s_id_decode = rb_intern("decode");
326
326
  s_id_encode = rb_intern("encode");
@@ -286,7 +286,7 @@ pg_tmbmt_coders( VALUE self )
286
286
  }
287
287
 
288
288
  void
289
- init_pg_type_map_by_mri_type()
289
+ init_pg_type_map_by_mri_type(void)
290
290
  {
291
291
  /*
292
292
  * Document-class: PG::TypeMapByMriType < PG::TypeMap
@@ -356,7 +356,7 @@ pg_tmbo_build_column_map( VALUE self, VALUE result )
356
356
 
357
357
 
358
358
  void
359
- init_pg_type_map_by_oid()
359
+ init_pg_type_map_by_oid(void)
360
360
  {
361
361
  s_id_decode = rb_intern("decode");
362
362
 
@@ -299,7 +299,7 @@ pg_tmir_s_allocate( VALUE klass )
299
299
 
300
300
 
301
301
  void
302
- init_pg_type_map_in_ruby()
302
+ init_pg_type_map_in_ruby(void)
303
303
  {
304
304
  s_id_fit_to_result = rb_intern("fit_to_result");
305
305
  s_id_fit_to_query = rb_intern("fit_to_query");
data/lib/pg/connection.rb CHANGED
@@ -93,6 +93,27 @@ class PG::Connection
93
93
  return connect_hash_to_string(iopts)
94
94
  end
95
95
 
96
+ # Return a String representation of the object suitable for debugging.
97
+ def inspect
98
+ str = self.to_s
99
+ str[-1,0] = if finished?
100
+ " finished"
101
+ else
102
+ stats = []
103
+ stats << " status=#{ PG.constants.grep(/CONNECTION_/).find{|c| PG.const_get(c) == status} }" if status != CONNECTION_OK
104
+ stats << " transaction_status=#{ PG.constants.grep(/PQTRANS_/).find{|c| PG.const_get(c) == transaction_status} }" if transaction_status != PG::PQTRANS_IDLE
105
+ stats << " nonblocking=#{ isnonblocking }" if isnonblocking
106
+ stats << " pipeline_status=#{ PG.constants.grep(/PQ_PIPELINE_/).find{|c| PG.const_get(c) == pipeline_status} }" if respond_to?(:pipeline_status) && pipeline_status != PG::PQ_PIPELINE_OFF
107
+ stats << " client_encoding=#{ get_client_encoding }" if get_client_encoding != "UTF8"
108
+ stats << " type_map_for_results=#{ type_map_for_results.to_s }" unless type_map_for_results.is_a?(PG::TypeMapAllStrings)
109
+ stats << " type_map_for_queries=#{ type_map_for_queries.to_s }" unless type_map_for_queries.is_a?(PG::TypeMapAllStrings)
110
+ stats << " encoder_for_put_copy_data=#{ encoder_for_put_copy_data.to_s }" if encoder_for_put_copy_data
111
+ stats << " decoder_for_get_copy_data=#{ decoder_for_get_copy_data.to_s }" if decoder_for_get_copy_data
112
+ " host=#{host} port=#{port} user=#{user}#{stats.join}"
113
+ end
114
+ return str
115
+ end
116
+
96
117
  # call-seq:
97
118
  # conn.copy_data( sql [, coder] ) {|sql_result| ... } -> PG::Result
98
119
  #
@@ -555,14 +576,17 @@ class PG::Connection
555
576
  if (timeo = conninfo_hash[:connect_timeout].to_i) && timeo > 0
556
577
  # Lowest timeout is 2 seconds - like in libpq
557
578
  timeo = [timeo, 2].max
558
- stop_time = timeo + Process.clock_gettime(Process::CLOCK_MONOTONIC)
579
+ host_count = conninfo_hash[:host].to_s.count(",") + 1
580
+ stop_time = timeo * host_count + Process.clock_gettime(Process::CLOCK_MONOTONIC)
559
581
  end
560
582
 
561
583
  poll_status = PG::PGRES_POLLING_WRITING
562
584
  until poll_status == PG::PGRES_POLLING_OK ||
563
585
  poll_status == PG::PGRES_POLLING_FAILED
564
586
 
565
- timeout = stop_time&.-(Process.clock_gettime(Process::CLOCK_MONOTONIC))
587
+ # Set single timeout to parameter "connect_timeout" but
588
+ # don't exceed total connection time of number-of-hosts * connect_timeout.
589
+ timeout = [timeo, stop_time - Process.clock_gettime(Process::CLOCK_MONOTONIC)].min if stop_time
566
590
  event = if !timeout || timeout >= 0
567
591
  # If the socket needs to read, wait 'til it becomes readable to poll again
568
592
  case poll_status
@@ -600,7 +624,6 @@ class PG::Connection
600
624
 
601
625
  # Check to see if it's finished or failed yet
602
626
  poll_status = send( poll_meth )
603
- @last_status = status unless [PG::CONNECTION_BAD, PG::CONNECTION_OK].include?(status)
604
627
  end
605
628
 
606
629
  unless status == PG::CONNECTION_OK
@@ -691,84 +714,49 @@ class PG::Connection
691
714
  iopts = PG::Connection.conninfo_parse(option_string).each_with_object({}){|h, o| o[h[:keyword].to_sym] = h[:val] if h[:val] }
692
715
  iopts = PG::Connection.conndefaults.each_with_object({}){|h, o| o[h[:keyword].to_sym] = h[:val] if h[:val] }.merge(iopts)
693
716
 
694
- errors = []
695
717
  if iopts[:hostaddr]
696
718
  # hostaddr is provided -> no need to resolve hostnames
697
- ihostaddrs = iopts[:hostaddr].split(",", -1)
698
719
 
699
- ihosts = iopts[:host].split(",", -1) if iopts[:host]
700
- raise PG::ConnectionBad, "could not match #{ihosts.size} host names to #{ihostaddrs.size} hostaddr values" if ihosts && ihosts.size != ihostaddrs.size
701
-
702
- iports = iopts[:port].split(",", -1)
703
- iports = iports * ihostaddrs.size if iports.size == 1
704
- raise PG::ConnectionBad, "could not match #{iports.size} port numbers to #{ihostaddrs.size} hosts" if iports.size != ihostaddrs.size
705
-
706
- # Try to connect to each hostaddr with separate timeout
707
- ihostaddrs.each_with_index do |ihostaddr, idx|
708
- oopts = iopts.merge(hostaddr: ihostaddr, port: iports[idx])
709
- oopts[:host] = ihosts[idx] if ihosts
710
- c = connect_internal(oopts, errors)
711
- return c if c
712
- end
713
- elsif iopts[:host] && !iopts[:host].empty?
714
- # Resolve DNS in Ruby to avoid blocking state while connecting, when it ...
720
+ elsif iopts[:host] && !iopts[:host].empty? && PG.library_version >= 100000
721
+ # Resolve DNS in Ruby to avoid blocking state while connecting.
722
+ # Multiple comma-separated values are generated, if the hostname resolves to both IPv4 and IPv6 addresses.
723
+ # This requires PostgreSQL-10+, so no DNS resolving is done on earlier versions.
715
724
  ihosts = iopts[:host].split(",", -1)
716
-
717
725
  iports = iopts[:port].split(",", -1)
718
726
  iports = iports * ihosts.size if iports.size == 1
719
727
  raise PG::ConnectionBad, "could not match #{iports.size} port numbers to #{ihosts.size} hosts" if iports.size != ihosts.size
720
728
 
721
- ihosts.each_with_index do |mhost, idx|
729
+ dests = ihosts.each_with_index.flat_map do |mhost, idx|
722
730
  unless host_is_named_pipe?(mhost)
723
- addrs = if Fiber.respond_to?(:scheduler) &&
731
+ if Fiber.respond_to?(:scheduler) &&
724
732
  Fiber.scheduler &&
725
733
  RUBY_VERSION < '3.1.'
726
734
 
727
735
  # Use a second thread to avoid blocking of the scheduler.
728
736
  # `TCPSocket.gethostbyname` isn't fiber aware before ruby-3.1.
729
- Thread.new{ Addrinfo.getaddrinfo(mhost, nil, nil, :STREAM).map(&:ip_address) rescue [''] }.value
737
+ hostaddrs = Thread.new{ Addrinfo.getaddrinfo(mhost, nil, nil, :STREAM).map(&:ip_address) rescue [''] }.value
730
738
  else
731
- Addrinfo.getaddrinfo(mhost, nil, nil, :STREAM).map(&:ip_address) rescue ['']
732
- end
733
-
734
- # Try to connect to each host with separate timeout
735
- addrs.each do |addr|
736
- oopts = iopts.merge(hostaddr: addr, host: mhost, port: iports[idx])
737
- c = connect_internal(oopts, errors)
738
- return c if c
739
+ hostaddrs = Addrinfo.getaddrinfo(mhost, nil, nil, :STREAM).map(&:ip_address) rescue ['']
739
740
  end
740
741
  else
741
742
  # No hostname to resolve (UnixSocket)
742
- oopts = iopts.merge(host: mhost, port: iports[idx])
743
- c = connect_internal(oopts, errors)
744
- return c if c
743
+ hostaddrs = [nil]
745
744
  end
745
+ hostaddrs.map { |hostaddr| [hostaddr, mhost, iports[idx]] }
746
746
  end
747
+ iopts.merge!(
748
+ hostaddr: dests.map{|d| d[0] }.join(","),
749
+ host: dests.map{|d| d[1] }.join(","),
750
+ port: dests.map{|d| d[2] }.join(","))
747
751
  else
748
752
  # No host given
749
- return connect_internal(iopts)
750
753
  end
751
- raise PG::ConnectionBad, errors.join("\n")
752
- end
753
-
754
- private def connect_internal(opts, errors=nil)
755
- begin
756
- conn = self.connect_start(opts) or
757
- raise(PG::Error, "Unable to create a new connection")
754
+ conn = self.connect_start(iopts) or
755
+ raise(PG::Error, "Unable to create a new connection")
758
756
 
759
- raise PG::ConnectionBad.new(conn.error_message, connection: self) if conn.status == PG::CONNECTION_BAD
757
+ raise PG::ConnectionBad, conn.error_message if conn.status == PG::CONNECTION_BAD
760
758
 
761
- conn.send(:async_connect_or_reset, :connect_poll)
762
- rescue PG::ConnectionBad => err
763
- if errors && !(conn && [PG::CONNECTION_AWAITING_RESPONSE].include?(conn.instance_variable_get(:@last_status)))
764
- # Seems to be no authentication error -> try next host
765
- errors << err
766
- return nil
767
- else
768
- # Probably an authentication error
769
- raise
770
- end
771
- end
759
+ conn.send(:async_connect_or_reset, :connect_poll)
772
760
  conn
773
761
  end
774
762
 
data/lib/pg/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module PG
2
2
  # Library version
3
- VERSION = '1.4.3'
3
+ VERSION = '1.4.4'
4
4
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.3
4
+ version: 1.4.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -11,32 +11,26 @@ bindir: bin
11
11
  cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
- MIIETTCCArWgAwIBAgIBATANBgkqhkiG9w0BAQsFADAoMSYwJAYDVQQDDB1sYXJz
15
- L0RDPWdyZWl6LXJlaW5zZG9yZi9EQz1kZTAeFw0yMjAyMTQxMzMwNTZaFw0yMzAy
16
- MTQxMzMwNTZaMCgxJjAkBgNVBAMMHWxhcnMvREM9Z3JlaXotcmVpbnNkb3JmL0RD
17
- PWRlMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAwum6Y1KznfpzXOT/
18
- mZgJTBbxZuuZF49Fq3K0WA67YBzNlDv95qzSp7V/7Ek3NCcnT7G+2kSuhNo1FhdN
19
- eSDO/moYebZNAcu3iqLsuzuULXPLuoU0GsMnVMqV9DZPh7cQHE5EBZ7hlzDBK7k/
20
- 8nBMvR0mHo77kIkapHc26UzVq/G0nKLfDsIHXVylto3PjzOumjG6GhmFN4r3cP6e
21
- SDfl1FSeRYVpt4kmQULz/zdSaOH3AjAq7PM2Z91iGwQvoUXMANH2v89OWjQO/NHe
22
- JMNDFsmHK/6Ji4Kk48Z3TyscHQnipAID5GhS1oD21/WePdj7GhmbF5gBzkV5uepd
23
- eJQPgWGwrQW/Z2oPjRuJrRofzWfrMWqbOahj9uth6WSxhNexUtbjk6P8emmXOJi5
24
- chQPnWX+N3Gj+jjYxqTFdwT7Mj3pv1VHa+aNUbqSPpvJeDyxRIuo9hvzDaBHb/Cg
25
- 9qRVcm8a96n4t7y2lrX1oookY6bkBaxWOMtWlqIprq8JZXM9AgMBAAGjgYEwfzAJ
26
- BgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUOIdbSMr3VFrTCO9/cTM0
27
- 0exHzBcwIgYDVR0RBBswGYEXbGFyc0BncmVpei1yZWluc2RvcmYuZGUwIgYDVR0S
28
- BBswGYEXbGFyc0BncmVpei1yZWluc2RvcmYuZGUwDQYJKoZIhvcNAQELBQADggGB
29
- AFWP7F/y3Oq3NgrqUOnjKOeDaBa7AqNhHS+PZg+C90lnJzMgOs4KKgZYxqSQVSab
30
- SCEmzIO/StkXY4NpJ4fYLrHemf/fJy1wPyu+fNdp5SEEUwEo+2toRFlzTe4u4LdS
31
- QC636nPPTMt8H3xz2wf/lUIUeo2Qc95Qt2BQM465ibbG9kmA3c7Sopx6yOabYOAl
32
- KPRbOSEPiWYcF9Suuz8Gdf8jxEtPlnZiwRvnYJ+IHMq3XQCJWPpMzdDMbtlgHbXE
33
- vq1zOTLMSYAS0UB3uionR4yo1hLz60odwkCm7qf0o2Ci/5OjtB0a89VuyqRU2vUJ
34
- QH95WBjDJ6lCCW7J0mrMPnJQSUFTmufsU6jOChvPaCeAzW1YwrsP/YKnvwueG7ip
35
- VOdW6RitjtFxhS7evRL0201+KUvLz12zZWWjOcujlQs64QprxOtiv/MiisKb1Ng+
36
- oL1mUdzB8KrZL4/WbG5YNX6UTtJbIOu9qEFbBAy4/jtIkJX+dlNoFwd4GXQW1YNO
37
- nA==
14
+ MIIDLjCCAhagAwIBAgIBCjANBgkqhkiG9w0BAQsFADA9MQ4wDAYDVQQDDAVrYW5p
15
+ czEXMBUGCgmSJomT8ixkARkWB2NvbWNhcmQxEjAQBgoJkiaJk/IsZAEZFgJkZTAe
16
+ Fw0yMjA0MTExMTMwNTNaFw0yMzA0MTExMTMwNTNaMD0xDjAMBgNVBAMMBWthbmlz
17
+ MRcwFQYKCZImiZPyLGQBGRYHY29tY2FyZDESMBAGCgmSJomT8ixkARkWAmRlMIIB
18
+ IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApop+rNmg35bzRugZ21VMGqI6
19
+ HGzPLO4VHYncWn/xmgPU/ZMcZdfj6MzIaZJ/czXyt4eHpBk1r8QOV3gBXnRXEjVW
20
+ 9xi+EdVOkTV2/AVFKThcbTAQGiF/bT1n2M+B1GTybRzMg6hyhOJeGPqIhLfJEpxn
21
+ lJi4+ENAVT4MpqHEAGB8yFoPC0GqiOHQsdHxQV3P3c2OZqG+yJey74QtwA2tLcLn
22
+ Q53c63+VLGsOjODl1yPn/2ejyq8qWu6ahfTxiIlSar2UbwtaQGBDFdb2CXgEufXT
23
+ L7oaPxlmj+Q2oLOfOnInd2Oxop59HoJCQPsg8f921J43NCQGA8VHK6paxIRDLQID
24
+ AQABozkwNzAJBgNVHRMEAjAAMAsGA1UdDwQEAwIEsDAdBgNVHQ4EFgQUvgTdT7fe
25
+ x17ugO3IOsjEJwW7KP4wDQYJKoZIhvcNAQELBQADggEBAILiaB/unSVBfX5n7uL8
26
+ veGGCOHuGYhCGqspb6mYiCx0dmV3RPRiEfGDLfzcXbHNx/3AjygcxH4Slr+pmaxr
27
+ 04Xli3WurocnjoANSWqCwpHH3OhSVxFgBNrCa3OMWcIr0xKH+I7PXA80SXe0pzfg
28
+ ePjpzTY71j+rcyRJqWiU5/zwdUaCCelBJscxh/0IaNcz67ocCEMRj0n4m5HFEmZL
29
+ 9zKkMZFoOjxRQjcL84QU7ZXnnFR5HG8nLw+NqWjo49W6MBQ9HGFda2tk3OpBhyWS
30
+ sc3NyOkGUGdfiee5VRG31Sh3LLON3YGED+zZAS+ZF6598y4vhv8MBLa1Oy357byC
31
+ tTg=
38
32
  -----END CERTIFICATE-----
39
- date: 2022-08-09 00:00:00.000000000 Z
33
+ date: 2022-10-11 00:00:00.000000000 Z
40
34
  dependencies: []
41
35
  description: Pg is the Ruby interface to the PostgreSQL RDBMS. It works with PostgreSQL
42
36
  9.3 and later.
@@ -179,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
173
  - !ruby/object:Gem::Version
180
174
  version: '0'
181
175
  requirements: []
182
- rubygems_version: 3.3.7
176
+ rubygems_version: 3.3.19
183
177
  signing_key:
184
178
  specification_version: 4
185
179
  summary: Pg is the Ruby interface to the PostgreSQL RDBMS
metadata.gz.sig CHANGED
Binary file