pg 1.0.0 → 1.2.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.tar.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +156 -0
- data/Manifest.txt +8 -2
- data/README-Windows.rdoc +4 -4
- data/README.ja.rdoc +1 -2
- data/README.rdoc +55 -9
- data/Rakefile +9 -7
- data/Rakefile.cross +58 -57
- data/ext/errorcodes.def +68 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +19 -2
- data/ext/extconf.rb +7 -5
- data/ext/pg.c +141 -98
- data/ext/pg.h +64 -21
- data/ext/pg_binary_decoder.c +82 -15
- data/ext/pg_binary_encoder.c +13 -12
- data/ext/pg_coder.c +73 -12
- data/ext/pg_connection.c +625 -346
- data/ext/pg_copy_coder.c +16 -8
- data/ext/pg_record_coder.c +491 -0
- data/ext/pg_result.c +571 -191
- data/ext/pg_text_decoder.c +606 -40
- data/ext/pg_text_encoder.c +185 -54
- data/ext/pg_tuple.c +549 -0
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +4 -4
- data/ext/pg_type_map_by_class.c +9 -4
- data/ext/pg_type_map_by_column.c +7 -6
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -2
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/{util.c → pg_util.c} +10 -10
- data/ext/{util.h → pg_util.h} +2 -2
- data/lib/pg.rb +8 -6
- data/lib/pg/basic_type_mapping.rb +121 -25
- data/lib/pg/binary_decoder.rb +23 -0
- data/lib/pg/coder.rb +23 -2
- data/lib/pg/connection.rb +22 -3
- data/lib/pg/constants.rb +2 -1
- data/lib/pg/exceptions.rb +2 -1
- data/lib/pg/result.rb +14 -2
- data/lib/pg/text_decoder.rb +21 -26
- data/lib/pg/text_encoder.rb +32 -8
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +3 -2
- data/spec/helpers.rb +52 -20
- data/spec/pg/basic_type_mapping_spec.rb +362 -37
- data/spec/pg/connection_spec.rb +376 -146
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +240 -15
- data/spec/pg/tuple_spec.rb +333 -0
- data/spec/pg/type_map_by_class_spec.rb +2 -2
- data/spec/pg/type_map_by_column_spec.rb +6 -2
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_map_by_oid_spec.rb +3 -3
- data/spec/pg/type_map_in_ruby_spec.rb +1 -1
- data/spec/pg/type_map_spec.rb +1 -1
- data/spec/pg/type_spec.rb +363 -17
- data/spec/pg_spec.rb +1 -1
- metadata +47 -47
- metadata.gz.sig +0 -0
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module PG
|
5
|
+
module BinaryDecoder
|
6
|
+
# Convenience classes for timezone options
|
7
|
+
class TimestampUtc < Timestamp
|
8
|
+
def initialize(params={})
|
9
|
+
super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_UTC))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
class TimestampUtcToLocal < Timestamp
|
13
|
+
def initialize(params={})
|
14
|
+
super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
class TimestampLocal < Timestamp
|
18
|
+
def initialize(params={})
|
19
|
+
super(params.merge(flags: PG::Coder::TIMESTAMP_DB_LOCAL | PG::Coder::TIMESTAMP_APP_LOCAL))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end # module PG
|
data/lib/pg/coder.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module PG
|
4
5
|
|
@@ -28,6 +29,7 @@ module PG
|
|
28
29
|
{
|
29
30
|
oid: oid,
|
30
31
|
format: format,
|
32
|
+
flags: flags,
|
31
33
|
name: name,
|
32
34
|
}
|
33
35
|
end
|
@@ -52,6 +54,18 @@ module PG
|
|
52
54
|
str[-1,0] = "#{name_str} #{oid_str}#{format_str}"
|
53
55
|
str
|
54
56
|
end
|
57
|
+
|
58
|
+
def inspect_short
|
59
|
+
str = case format
|
60
|
+
when 0 then "T"
|
61
|
+
when 1 then "B"
|
62
|
+
else format.to_s
|
63
|
+
end
|
64
|
+
str += "E" if respond_to?(:encode)
|
65
|
+
str += "D" if respond_to?(:decode)
|
66
|
+
|
67
|
+
"#{name || self.class.name}:#{str}"
|
68
|
+
end
|
55
69
|
end
|
56
70
|
|
57
71
|
class CompositeCoder < Coder
|
@@ -79,5 +93,12 @@ module PG
|
|
79
93
|
})
|
80
94
|
end
|
81
95
|
end
|
82
|
-
end # module PG
|
83
96
|
|
97
|
+
class RecordCoder < Coder
|
98
|
+
def to_h
|
99
|
+
super.merge!({
|
100
|
+
type_map: type_map,
|
101
|
+
})
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end # module PG
|
data/lib/pg/connection.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'pg' unless defined?( PG )
|
4
5
|
require 'uri'
|
@@ -47,7 +48,7 @@ class PG::Connection
|
|
47
48
|
|
48
49
|
if args.length == 1
|
49
50
|
case args.first
|
50
|
-
when URI, /\A#{URI
|
51
|
+
when URI, /\A#{URI::ABS_URI_REF}\z/
|
51
52
|
uri = URI(args.first)
|
52
53
|
options.merge!( Hash[URI.decode_www_form( uri.query )] ) if uri.query
|
53
54
|
when /=/
|
@@ -268,5 +269,23 @@ class PG::Connection
|
|
268
269
|
end
|
269
270
|
end
|
270
271
|
|
271
|
-
|
272
|
+
REDIRECT_METHODS = {
|
273
|
+
:exec => [:async_exec, :sync_exec],
|
274
|
+
:query => [:async_exec, :sync_exec],
|
275
|
+
:exec_params => [:async_exec_params, :sync_exec_params],
|
276
|
+
:prepare => [:async_prepare, :sync_prepare],
|
277
|
+
:exec_prepared => [:async_exec_prepared, :sync_exec_prepared],
|
278
|
+
:describe_portal => [:async_describe_portal, :sync_describe_portal],
|
279
|
+
:describe_prepared => [:async_describe_prepared, :sync_describe_prepared],
|
280
|
+
}
|
272
281
|
|
282
|
+
def self.async_api=(enable)
|
283
|
+
REDIRECT_METHODS.each do |ali, (async, sync)|
|
284
|
+
remove_method(ali) if method_defined?(ali)
|
285
|
+
alias_method( ali, enable ? async : sync )
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
# pg-1.1.0+ defaults to libpq's async API for query related blocking methods
|
290
|
+
self.async_api = true
|
291
|
+
end # class PG::Connection
|
data/lib/pg/constants.rb
CHANGED
data/lib/pg/exceptions.rb
CHANGED
data/lib/pg/result.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'pg' unless defined?( PG )
|
4
5
|
|
@@ -9,12 +10,23 @@ class PG::Result
|
|
9
10
|
#
|
10
11
|
# +type_map+: a PG::TypeMap instance.
|
11
12
|
#
|
12
|
-
#
|
13
|
+
# This method is equal to #type_map= , but returns self, so that calls can be chained.
|
14
|
+
#
|
15
|
+
# See also PG::BasicTypeMapForResults
|
13
16
|
def map_types!(type_map)
|
14
17
|
self.type_map = type_map
|
15
18
|
return self
|
16
19
|
end
|
17
20
|
|
21
|
+
# Set the data type for all field name returning methods.
|
22
|
+
#
|
23
|
+
# +type+: a Symbol defining the field name type.
|
24
|
+
#
|
25
|
+
# This method is equal to #field_name_type= , but returns self, so that calls can be chained.
|
26
|
+
def field_names_as(type)
|
27
|
+
self.field_name_type = type
|
28
|
+
return self
|
29
|
+
end
|
18
30
|
|
19
31
|
### Return a String representation of the object suitable for debugging.
|
20
32
|
def inspect
|
data/lib/pg/text_decoder.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'date'
|
4
5
|
require 'json'
|
@@ -6,10 +7,8 @@ require 'json'
|
|
6
7
|
module PG
|
7
8
|
module TextDecoder
|
8
9
|
class Date < SimpleDecoder
|
9
|
-
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
10
|
-
|
11
10
|
def decode(string, tuple=nil, field=nil)
|
12
|
-
if string =~
|
11
|
+
if string =~ /\A(\d{4})-(\d\d)-(\d\d)\z/
|
13
12
|
::Date.new $1.to_i, $2.to_i, $3.to_i
|
14
13
|
else
|
15
14
|
string
|
@@ -17,35 +16,31 @@ module PG
|
|
17
16
|
end
|
18
17
|
end
|
19
18
|
|
20
|
-
class
|
21
|
-
ISO_DATETIME_WITHOUT_TIMEZONE = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
|
22
|
-
|
19
|
+
class JSON < SimpleDecoder
|
23
20
|
def decode(string, tuple=nil, field=nil)
|
24
|
-
|
25
|
-
Time.new $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, "#{$6}#{$7}".to_r
|
26
|
-
else
|
27
|
-
string
|
28
|
-
end
|
21
|
+
::JSON.parse(string, quirks_mode: true)
|
29
22
|
end
|
30
23
|
end
|
31
24
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
if string =~ ISO_DATETIME_WITH_TIMEZONE
|
37
|
-
Time.new $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, "#{$6}#{$7}".to_r, "#{$8}:#{$9 || '00'}:#{$10 || '00'}"
|
38
|
-
else
|
39
|
-
string
|
40
|
-
end
|
25
|
+
# Convenience classes for timezone options
|
26
|
+
class TimestampUtc < Timestamp
|
27
|
+
def initialize(params={})
|
28
|
+
super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_UTC))
|
41
29
|
end
|
42
30
|
end
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
31
|
+
class TimestampUtcToLocal < Timestamp
|
32
|
+
def initialize(params={})
|
33
|
+
super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
class TimestampLocal < Timestamp
|
37
|
+
def initialize(params={})
|
38
|
+
super(params.merge(flags: PG::Coder::TIMESTAMP_DB_LOCAL | PG::Coder::TIMESTAMP_APP_LOCAL))
|
47
39
|
end
|
48
40
|
end
|
41
|
+
|
42
|
+
# For backward compatibility:
|
43
|
+
TimestampWithoutTimeZone = TimestampLocal
|
44
|
+
TimestampWithTimeZone = Timestamp
|
49
45
|
end
|
50
46
|
end # module PG
|
51
|
-
|
data/lib/pg/text_encoder.rb
CHANGED
@@ -1,27 +1,32 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'json'
|
5
|
+
require 'ipaddr'
|
4
6
|
|
5
7
|
module PG
|
6
8
|
module TextEncoder
|
7
9
|
class Date < SimpleEncoder
|
8
|
-
STRFTIME_ISO_DATE = "%Y-%m-%d".freeze
|
9
10
|
def encode(value)
|
10
|
-
value.respond_to?(:strftime) ? value.strftime(
|
11
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d") : value
|
11
12
|
end
|
12
13
|
end
|
13
14
|
|
14
15
|
class TimestampWithoutTimeZone < SimpleEncoder
|
15
|
-
STRFTIME_ISO_DATETIME_WITHOUT_TIMEZONE = "%Y-%m-%d %H:%M:%S.%N".freeze
|
16
16
|
def encode(value)
|
17
|
-
value.respond_to?(:strftime) ? value.strftime(
|
17
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N") : value
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class TimestampUtc < SimpleEncoder
|
22
|
+
def encode(value)
|
23
|
+
value.respond_to?(:utc) ? value.utc.strftime("%Y-%m-%d %H:%M:%S.%N") : value
|
18
24
|
end
|
19
25
|
end
|
20
26
|
|
21
27
|
class TimestampWithTimeZone < SimpleEncoder
|
22
|
-
STRFTIME_ISO_DATETIME_WITH_TIMEZONE = "%Y-%m-%d %H:%M:%S.%N %:z".freeze
|
23
28
|
def encode(value)
|
24
|
-
value.respond_to?(:strftime) ? value.strftime(
|
29
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N %:z") : value
|
25
30
|
end
|
26
31
|
end
|
27
32
|
|
@@ -30,6 +35,25 @@ module PG
|
|
30
35
|
::JSON.generate(value, quirks_mode: true)
|
31
36
|
end
|
32
37
|
end
|
38
|
+
|
39
|
+
class Inet < SimpleEncoder
|
40
|
+
def encode(value)
|
41
|
+
case value
|
42
|
+
when IPAddr
|
43
|
+
default_prefix = (value.family == Socket::AF_INET ? 32 : 128)
|
44
|
+
s = value.to_s
|
45
|
+
if value.respond_to?(:prefix)
|
46
|
+
prefix = value.prefix
|
47
|
+
else
|
48
|
+
range = value.to_range
|
49
|
+
prefix = default_prefix - Math.log(((range.end.to_i - range.begin.to_i) + 1), 2).to_i
|
50
|
+
end
|
51
|
+
s << "/" << prefix.to_s if prefix != default_prefix
|
52
|
+
s
|
53
|
+
else
|
54
|
+
value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
33
58
|
end
|
34
59
|
end # module PG
|
35
|
-
|
data/lib/pg/tuple.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pg' unless defined?( PG )
|
5
|
+
|
6
|
+
|
7
|
+
class PG::Tuple
|
8
|
+
|
9
|
+
### Return a String representation of the object suitable for debugging.
|
10
|
+
def inspect
|
11
|
+
"#<#{self.class} #{self.map{|k,v| "#{k}: #{v.inspect}" }.join(", ") }>"
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_key?(key)
|
15
|
+
field_map.has_key?(key)
|
16
|
+
end
|
17
|
+
alias key? has_key?
|
18
|
+
|
19
|
+
def keys
|
20
|
+
field_names || field_map.keys.freeze
|
21
|
+
end
|
22
|
+
|
23
|
+
def each_key(&block)
|
24
|
+
if fn=field_names
|
25
|
+
fn.each(&block)
|
26
|
+
else
|
27
|
+
field_map.each_key(&block)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'pg' unless defined?( PG )
|
4
5
|
|
@@ -9,7 +10,7 @@ class PG::TypeMapByColumn
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def inspect
|
12
|
-
type_strings = coders.map{|c| c ?
|
13
|
+
type_strings = coders.map{|c| c ? c.inspect_short : 'nil' }
|
13
14
|
"#<#{self.class} #{type_strings.join(' ')}>"
|
14
15
|
end
|
15
16
|
end
|
data/spec/helpers.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'rspec'
|
@@ -22,12 +22,11 @@ module PG::TestingHelpers
|
|
22
22
|
|
23
23
|
mod.around( :each ) do |example|
|
24
24
|
begin
|
25
|
+
@conn.set_default_encoding
|
25
26
|
@conn.exec( 'BEGIN' ) unless example.metadata[:without_transaction]
|
26
|
-
|
27
|
-
|
28
|
-
@conn.
|
29
|
-
[@conn.escape_string(desc.slice(-60))]
|
30
|
-
end
|
27
|
+
desc = example.source_location.join(':')
|
28
|
+
@conn.exec %Q{SET application_name TO '%s'} %
|
29
|
+
[@conn.escape_string(desc.slice(-60))]
|
31
30
|
example.run
|
32
31
|
ensure
|
33
32
|
@conn.exec( 'ROLLBACK' ) unless example.metadata[:without_transaction]
|
@@ -173,18 +172,18 @@ module PG::TestingHelpers
|
|
173
172
|
datadir = testdir + 'data'
|
174
173
|
pidfile = datadir + 'postmaster.pid'
|
175
174
|
if pidfile.exist? && pid = pidfile.read.chomp.to_i
|
176
|
-
|
175
|
+
trace "pidfile (%p) exists: %d" % [ pidfile, pid ]
|
177
176
|
begin
|
178
177
|
Process.kill( 0, pid )
|
179
178
|
rescue Errno::ESRCH
|
180
|
-
|
179
|
+
trace "No postmaster running for %s" % [ datadir ]
|
181
180
|
# Process isn't alive, so don't try to stop it
|
182
181
|
else
|
183
|
-
|
182
|
+
trace "Stopping lingering database at PID %d" % [ pid ]
|
184
183
|
run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
|
185
184
|
end
|
186
185
|
else
|
187
|
-
|
186
|
+
trace "No pidfile (%p)" % [ pidfile ]
|
188
187
|
end
|
189
188
|
end
|
190
189
|
end
|
@@ -195,12 +194,12 @@ module PG::TestingHelpers
|
|
195
194
|
require 'pg'
|
196
195
|
stop_existing_postmasters()
|
197
196
|
|
198
|
-
|
197
|
+
trace "Setting up test database for #{description}"
|
199
198
|
@test_pgdata = TEST_DIRECTORY + 'data'
|
200
199
|
@test_pgdata.mkpath
|
201
200
|
|
202
|
-
|
203
|
-
ENV['PGPORT']
|
201
|
+
ENV['PGPORT'] ||= "54321"
|
202
|
+
@port = ENV['PGPORT'].to_i
|
204
203
|
ENV['PGHOST'] = 'localhost'
|
205
204
|
@conninfo = "host=localhost port=#{@port} dbname=test"
|
206
205
|
|
@@ -210,7 +209,7 @@ module PG::TestingHelpers
|
|
210
209
|
begin
|
211
210
|
unless (@test_pgdata+"postgresql.conf").exist?
|
212
211
|
FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
|
213
|
-
|
212
|
+
trace "Running initdb"
|
214
213
|
log_and_run @logfile, 'initdb', '-E', 'UTF8', '--no-locale', '-D', @test_pgdata.to_s
|
215
214
|
end
|
216
215
|
|
@@ -219,14 +218,14 @@ module PG::TestingHelpers
|
|
219
218
|
'-D', @test_pgdata.to_s, 'start'
|
220
219
|
sleep 2
|
221
220
|
|
222
|
-
|
221
|
+
trace "Creating the test DB"
|
223
222
|
log_and_run @logfile, 'psql', '-e', '-c', 'DROP DATABASE IF EXISTS test', 'postgres'
|
224
223
|
log_and_run @logfile, 'createdb', '-e', 'test'
|
225
224
|
|
226
225
|
rescue => err
|
227
226
|
$stderr.puts "%p during test setup: %s" % [ err.class, err.message ]
|
228
227
|
$stderr.puts "See #{@logfile} for details."
|
229
|
-
$stderr.puts
|
228
|
+
$stderr.puts err.backtrace if $DEBUG
|
230
229
|
fail
|
231
230
|
end
|
232
231
|
|
@@ -240,7 +239,7 @@ module PG::TestingHelpers
|
|
240
239
|
|
241
240
|
|
242
241
|
def teardown_testing_db( conn )
|
243
|
-
|
242
|
+
trace "Tearing down test database"
|
244
243
|
|
245
244
|
if conn
|
246
245
|
check_for_lingering_connections( conn )
|
@@ -266,7 +265,7 @@ module PG::TestingHelpers
|
|
266
265
|
|
267
266
|
# Retrieve the names of the column types of a given result set.
|
268
267
|
def result_typenames(res)
|
269
|
-
@conn.
|
268
|
+
@conn.exec_params( "SELECT " + res.nfields.times.map{|i| "format_type($#{i*2+1},$#{i*2+2})"}.join(","),
|
270
269
|
res.nfields.times.map{|i| [res.ftype(i), res.fmod(i)] }.flatten ).
|
271
270
|
values[0]
|
272
271
|
end
|
@@ -320,6 +319,39 @@ module PG::TestingHelpers
|
|
320
319
|
return ConnStillUsableMatcher.new
|
321
320
|
end
|
322
321
|
|
322
|
+
def wait_for_polling_ok(conn, meth = :connect_poll)
|
323
|
+
status = conn.send(meth)
|
324
|
+
|
325
|
+
while status != PG::PGRES_POLLING_OK
|
326
|
+
if status == PG::PGRES_POLLING_READING
|
327
|
+
select( [conn.socket_io], [], [], 5.0 ) or
|
328
|
+
raise "Asynchronous connection timed out!"
|
329
|
+
|
330
|
+
elsif status == PG::PGRES_POLLING_WRITING
|
331
|
+
select( [], [conn.socket_io], [], 5.0 ) or
|
332
|
+
raise "Asynchronous connection timed out!"
|
333
|
+
end
|
334
|
+
status = conn.send(meth)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def wait_for_query_result(conn)
|
339
|
+
result = nil
|
340
|
+
loop do
|
341
|
+
# Buffer any incoming data on the socket until a full result is ready.
|
342
|
+
conn.consume_input
|
343
|
+
while conn.is_busy
|
344
|
+
select( [conn.socket_io], nil, nil, 5.0 ) or
|
345
|
+
raise "Timeout waiting for query response."
|
346
|
+
conn.consume_input
|
347
|
+
end
|
348
|
+
|
349
|
+
# Fetch the next result. If there isn't one, the query is finished
|
350
|
+
result = conn.get_result || break
|
351
|
+
end
|
352
|
+
result
|
353
|
+
end
|
354
|
+
|
323
355
|
end
|
324
356
|
|
325
357
|
|
@@ -338,11 +370,11 @@ RSpec.configure do |config|
|
|
338
370
|
else
|
339
371
|
config.filter_run_excluding :windows
|
340
372
|
end
|
341
|
-
config.filter_run_excluding :socket_io unless
|
342
|
-
PG::Connection.instance_methods.map( &:to_sym ).include?( :socket_io )
|
343
373
|
|
344
374
|
config.filter_run_excluding( :postgresql_93 ) if PG.library_version < 90300
|
345
375
|
config.filter_run_excluding( :postgresql_94 ) if PG.library_version < 90400
|
346
376
|
config.filter_run_excluding( :postgresql_95 ) if PG.library_version < 90500
|
377
|
+
config.filter_run_excluding( :postgresql_96 ) if PG.library_version < 90600
|
347
378
|
config.filter_run_excluding( :postgresql_10 ) if PG.library_version < 100000
|
379
|
+
config.filter_run_excluding( :postgresql_12 ) if PG.library_version < 120000
|
348
380
|
end
|