pg 0.17.1 → 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 +5 -5
- checksums.yaml.gz.sig +0 -0
- data/BSDL +2 -2
- data/ChangeLog +0 -3506
- data/History.rdoc +308 -0
- data/Manifest.txt +35 -19
- data/README-Windows.rdoc +17 -28
- data/README.ja.rdoc +1 -2
- data/README.rdoc +113 -14
- data/Rakefile +67 -30
- data/Rakefile.cross +109 -83
- data/ext/errorcodes.def +101 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +33 -2
- data/ext/extconf.rb +55 -58
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +27 -39
- data/ext/pg.c +262 -130
- data/ext/pg.h +266 -54
- data/ext/pg_binary_decoder.c +229 -0
- data/ext/pg_binary_encoder.c +163 -0
- data/ext/pg_coder.c +561 -0
- data/ext/pg_connection.c +1689 -990
- data/ext/pg_copy_coder.c +599 -0
- data/ext/pg_errors.c +6 -0
- data/ext/pg_record_coder.c +491 -0
- data/ext/pg_result.c +897 -164
- data/ext/pg_text_decoder.c +987 -0
- data/ext/pg_text_encoder.c +814 -0
- data/ext/pg_tuple.c +549 -0
- data/ext/pg_type_map.c +166 -0
- data/ext/pg_type_map_all_strings.c +116 -0
- data/ext/pg_type_map_by_class.c +244 -0
- data/ext/pg_type_map_by_column.c +313 -0
- data/ext/pg_type_map_by_mri_type.c +284 -0
- data/ext/pg_type_map_by_oid.c +356 -0
- data/ext/pg_type_map_in_ruby.c +299 -0
- data/ext/pg_util.c +149 -0
- data/ext/pg_util.h +65 -0
- data/lib/pg/basic_type_mapping.rb +522 -0
- data/lib/pg/binary_decoder.rb +23 -0
- data/lib/pg/coder.rb +104 -0
- data/lib/pg/connection.rb +153 -41
- data/lib/pg/constants.rb +2 -1
- data/lib/pg/exceptions.rb +2 -1
- data/lib/pg/result.rb +33 -6
- data/lib/pg/text_decoder.rb +46 -0
- data/lib/pg/text_encoder.rb +59 -0
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +16 -0
- data/lib/pg.rb +29 -9
- data/spec/{lib/helpers.rb → helpers.rb} +151 -64
- data/spec/pg/basic_type_mapping_spec.rb +630 -0
- data/spec/pg/connection_spec.rb +1180 -477
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +456 -120
- data/spec/pg/tuple_spec.rb +333 -0
- data/spec/pg/type_map_by_class_spec.rb +138 -0
- data/spec/pg/type_map_by_column_spec.rb +226 -0
- data/spec/pg/type_map_by_mri_type_spec.rb +136 -0
- data/spec/pg/type_map_by_oid_spec.rb +149 -0
- data/spec/pg/type_map_in_ruby_spec.rb +164 -0
- data/spec/pg/type_map_spec.rb +22 -0
- data/spec/pg/type_spec.rb +1123 -0
- data/spec/pg_spec.rb +26 -20
- data.tar.gz.sig +0 -0
- metadata +148 -91
- metadata.gz.sig +0 -0
- data/sample/array_insert.rb +0 -20
- data/sample/async_api.rb +0 -106
- data/sample/async_copyto.rb +0 -39
- data/sample/async_mixed.rb +0 -56
- data/sample/check_conn.rb +0 -21
- data/sample/copyfrom.rb +0 -81
- data/sample/copyto.rb +0 -19
- data/sample/cursor.rb +0 -21
- data/sample/disk_usage_report.rb +0 -186
- data/sample/issue-119.rb +0 -94
- data/sample/losample.rb +0 -69
- data/sample/minimal-testcase.rb +0 -17
- data/sample/notify_wait.rb +0 -72
- data/sample/pg_statistics.rb +0 -294
- data/sample/replication_monitor.rb +0 -231
- data/sample/test_binary_values.rb +0 -33
- data/sample/wal_shipper.rb +0 -434
- data/sample/warehouse_partitions.rb +0 -320
@@ -0,0 +1,46 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'date'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module PG
|
8
|
+
module TextDecoder
|
9
|
+
class Date < SimpleDecoder
|
10
|
+
def decode(string, tuple=nil, field=nil)
|
11
|
+
if string =~ /\A(\d{4})-(\d\d)-(\d\d)\z/
|
12
|
+
::Date.new $1.to_i, $2.to_i, $3.to_i
|
13
|
+
else
|
14
|
+
string
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class JSON < SimpleDecoder
|
20
|
+
def decode(string, tuple=nil, field=nil)
|
21
|
+
::JSON.parse(string, quirks_mode: true)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
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))
|
29
|
+
end
|
30
|
+
end
|
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))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# For backward compatibility:
|
43
|
+
TimestampWithoutTimeZone = TimestampLocal
|
44
|
+
TimestampWithTimeZone = Timestamp
|
45
|
+
end
|
46
|
+
end # module PG
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'json'
|
5
|
+
require 'ipaddr'
|
6
|
+
|
7
|
+
module PG
|
8
|
+
module TextEncoder
|
9
|
+
class Date < SimpleEncoder
|
10
|
+
def encode(value)
|
11
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d") : value
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TimestampWithoutTimeZone < SimpleEncoder
|
16
|
+
def encode(value)
|
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
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class TimestampWithTimeZone < SimpleEncoder
|
28
|
+
def encode(value)
|
29
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N %:z") : value
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class JSON < SimpleEncoder
|
34
|
+
def encode(value)
|
35
|
+
::JSON.generate(value, quirks_mode: true)
|
36
|
+
end
|
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
|
58
|
+
end
|
59
|
+
end # module PG
|
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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require 'pg' unless defined?( PG )
|
5
|
+
|
6
|
+
class PG::TypeMapByColumn
|
7
|
+
# Returns the type oids of the assigned coders.
|
8
|
+
def oids
|
9
|
+
coders.map{|c| c.oid if c }
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
type_strings = coders.map{|c| c ? c.inspect_short : 'nil' }
|
14
|
+
"#<#{self.class} #{type_strings.join(' ')}>"
|
15
|
+
end
|
16
|
+
end
|
data/lib/pg.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
begin
|
4
5
|
require 'pg_ext'
|
@@ -7,7 +8,24 @@ rescue LoadError
|
|
7
8
|
if RUBY_PLATFORM =~/(mswin|mingw)/i
|
8
9
|
major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
|
9
10
|
raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
|
10
|
-
|
11
|
+
|
12
|
+
add_dll_path = proc do |path, &block|
|
13
|
+
begin
|
14
|
+
require 'ruby_installer/runtime'
|
15
|
+
RubyInstaller::Runtime.add_dll_directory(path, &block)
|
16
|
+
rescue LoadError
|
17
|
+
old_path = ENV['PATH']
|
18
|
+
ENV['PATH'] = "#{path};#{old_path}"
|
19
|
+
block.call
|
20
|
+
ENV['PATH'] = old_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Temporary add this directory for DLL search, so that libpq.dll can be found.
|
25
|
+
# mingw32-platform strings differ (RUBY_PLATFORM=i386-mingw32 vs. x86-mingw32 for rubygems)
|
26
|
+
add_dll_path.call(File.join(__dir__, RUBY_PLATFORM.gsub(/^i386-/, "x86-"))) do
|
27
|
+
require "#{major_minor}/pg_ext"
|
28
|
+
end
|
11
29
|
else
|
12
30
|
raise
|
13
31
|
end
|
@@ -19,10 +37,10 @@ end
|
|
19
37
|
module PG
|
20
38
|
|
21
39
|
# Library version
|
22
|
-
VERSION = '
|
40
|
+
VERSION = '1.2.3'
|
23
41
|
|
24
42
|
# VCS revision
|
25
|
-
REVISION = %q$Revision:
|
43
|
+
REVISION = %q$Revision: 6f611e78845a $
|
26
44
|
|
27
45
|
class NotAllCopyDataRetrieved < PG::Error
|
28
46
|
end
|
@@ -43,12 +61,14 @@ module PG
|
|
43
61
|
|
44
62
|
require 'pg/exceptions'
|
45
63
|
require 'pg/constants'
|
64
|
+
require 'pg/coder'
|
65
|
+
require 'pg/binary_decoder'
|
66
|
+
require 'pg/text_encoder'
|
67
|
+
require 'pg/text_decoder'
|
68
|
+
require 'pg/basic_type_mapping'
|
69
|
+
require 'pg/type_map_by_column'
|
46
70
|
require 'pg/connection'
|
47
71
|
require 'pg/result'
|
72
|
+
require 'pg/tuple'
|
48
73
|
|
49
74
|
end # module PG
|
50
|
-
|
51
|
-
|
52
|
-
# Backward-compatible aliase
|
53
|
-
PGError = PG::Error
|
54
|
-
|
@@ -1,14 +1,47 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'rspec'
|
5
5
|
require 'shellwords'
|
6
6
|
require 'pg'
|
7
7
|
|
8
|
-
|
8
|
+
DEFAULT_TEST_DIR_STR = File.join(Dir.pwd, "tmp_test_specs")
|
9
|
+
TEST_DIR_STR = ENV['RUBY_PG_TEST_DIR'] || DEFAULT_TEST_DIR_STR
|
10
|
+
TEST_DIRECTORY = Pathname.new(TEST_DIR_STR)
|
9
11
|
|
10
12
|
module PG::TestingHelpers
|
11
13
|
|
14
|
+
### Automatically set up the database when it's used, and wrap a transaction around
|
15
|
+
### examples that don't disable it.
|
16
|
+
def self::included( mod )
|
17
|
+
super
|
18
|
+
|
19
|
+
if mod.respond_to?( :around )
|
20
|
+
|
21
|
+
mod.before( :all ) { @conn = setup_testing_db(described_class ? described_class.name : mod.description) }
|
22
|
+
|
23
|
+
mod.around( :each ) do |example|
|
24
|
+
begin
|
25
|
+
@conn.set_default_encoding
|
26
|
+
@conn.exec( 'BEGIN' ) unless example.metadata[:without_transaction]
|
27
|
+
desc = example.source_location.join(':')
|
28
|
+
@conn.exec %Q{SET application_name TO '%s'} %
|
29
|
+
[@conn.escape_string(desc.slice(-60))]
|
30
|
+
example.run
|
31
|
+
ensure
|
32
|
+
@conn.exec( 'ROLLBACK' ) unless example.metadata[:without_transaction]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
mod.after( :all ) { teardown_testing_db(@conn) }
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
#
|
43
|
+
# Examples
|
44
|
+
#
|
12
45
|
|
13
46
|
# Set some ANSI escape code constants (Shamelessly stolen from Perl's
|
14
47
|
# Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
|
@@ -121,28 +154,9 @@ module PG::TestingHelpers
|
|
121
154
|
end
|
122
155
|
|
123
156
|
# Eliminate the noise of creating/tearing down the database by
|
124
|
-
# redirecting STDERR/STDOUT to a logfile
|
125
|
-
# supports fork()
|
157
|
+
# redirecting STDERR/STDOUT to a logfile
|
126
158
|
logfh = File.open( logpath, File::WRONLY|File::CREAT|File::APPEND )
|
127
|
-
|
128
|
-
pid = fork
|
129
|
-
rescue NotImplementedError
|
130
|
-
logfh.close
|
131
|
-
system( *cmd )
|
132
|
-
else
|
133
|
-
if pid
|
134
|
-
logfh.close
|
135
|
-
else
|
136
|
-
$stdout.reopen( logfh )
|
137
|
-
$stderr.reopen( $stdout )
|
138
|
-
$stderr.puts( ">>> " + cmd.shelljoin )
|
139
|
-
exec( *cmd )
|
140
|
-
$stderr.puts "After the exec()?!??!"
|
141
|
-
exit!
|
142
|
-
end
|
143
|
-
|
144
|
-
Process.wait( pid )
|
145
|
-
end
|
159
|
+
system( *cmd, [STDOUT, STDERR] => logfh )
|
146
160
|
|
147
161
|
raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
|
148
162
|
end
|
@@ -158,18 +172,18 @@ module PG::TestingHelpers
|
|
158
172
|
datadir = testdir + 'data'
|
159
173
|
pidfile = datadir + 'postmaster.pid'
|
160
174
|
if pidfile.exist? && pid = pidfile.read.chomp.to_i
|
161
|
-
|
175
|
+
trace "pidfile (%p) exists: %d" % [ pidfile, pid ]
|
162
176
|
begin
|
163
177
|
Process.kill( 0, pid )
|
164
178
|
rescue Errno::ESRCH
|
165
|
-
|
179
|
+
trace "No postmaster running for %s" % [ datadir ]
|
166
180
|
# Process isn't alive, so don't try to stop it
|
167
181
|
else
|
168
|
-
|
182
|
+
trace "Stopping lingering database at PID %d" % [ pid ]
|
169
183
|
run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
|
170
184
|
end
|
171
185
|
else
|
172
|
-
|
186
|
+
trace "No pidfile (%p)" % [ pidfile ]
|
173
187
|
end
|
174
188
|
end
|
175
189
|
end
|
@@ -180,12 +194,12 @@ module PG::TestingHelpers
|
|
180
194
|
require 'pg'
|
181
195
|
stop_existing_postmasters()
|
182
196
|
|
183
|
-
|
197
|
+
trace "Setting up test database for #{description}"
|
184
198
|
@test_pgdata = TEST_DIRECTORY + 'data'
|
185
199
|
@test_pgdata.mkpath
|
186
200
|
|
187
|
-
|
188
|
-
ENV['PGPORT']
|
201
|
+
ENV['PGPORT'] ||= "54321"
|
202
|
+
@port = ENV['PGPORT'].to_i
|
189
203
|
ENV['PGHOST'] = 'localhost'
|
190
204
|
@conninfo = "host=localhost port=#{@port} dbname=test"
|
191
205
|
|
@@ -195,7 +209,7 @@ module PG::TestingHelpers
|
|
195
209
|
begin
|
196
210
|
unless (@test_pgdata+"postgresql.conf").exist?
|
197
211
|
FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
|
198
|
-
|
212
|
+
trace "Running initdb"
|
199
213
|
log_and_run @logfile, 'initdb', '-E', 'UTF8', '--no-locale', '-D', @test_pgdata.to_s
|
200
214
|
end
|
201
215
|
|
@@ -204,14 +218,14 @@ module PG::TestingHelpers
|
|
204
218
|
'-D', @test_pgdata.to_s, 'start'
|
205
219
|
sleep 2
|
206
220
|
|
207
|
-
|
221
|
+
trace "Creating the test DB"
|
208
222
|
log_and_run @logfile, 'psql', '-e', '-c', 'DROP DATABASE IF EXISTS test', 'postgres'
|
209
223
|
log_and_run @logfile, 'createdb', '-e', 'test'
|
210
224
|
|
211
225
|
rescue => err
|
212
226
|
$stderr.puts "%p during test setup: %s" % [ err.class, err.message ]
|
213
227
|
$stderr.puts "See #{@logfile} for details."
|
214
|
-
$stderr.puts
|
228
|
+
$stderr.puts err.backtrace if $DEBUG
|
215
229
|
fail
|
216
230
|
end
|
217
231
|
|
@@ -225,7 +239,7 @@ module PG::TestingHelpers
|
|
225
239
|
|
226
240
|
|
227
241
|
def teardown_testing_db( conn )
|
228
|
-
|
242
|
+
trace "Tearing down test database"
|
229
243
|
|
230
244
|
if conn
|
231
245
|
check_for_lingering_connections( conn )
|
@@ -238,56 +252,129 @@ module PG::TestingHelpers
|
|
238
252
|
|
239
253
|
def check_for_lingering_connections( conn )
|
240
254
|
conn.exec( "SELECT * FROM pg_stat_activity" ) do |res|
|
241
|
-
conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid }
|
255
|
+
conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid && ["client backend", nil].include?(row["backend_type"]) }
|
242
256
|
unless conns.empty?
|
243
257
|
puts "Lingering connections remain:"
|
244
258
|
conns.each do |row|
|
245
|
-
puts " [%
|
259
|
+
puts " [%s] {%s} %s -- %s" % row.values_at( 'pid', 'state', 'application_name', 'query' )
|
246
260
|
end
|
247
261
|
end
|
248
262
|
end
|
249
263
|
end
|
250
264
|
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
265
|
+
|
266
|
+
# Retrieve the names of the column types of a given result set.
|
267
|
+
def result_typenames(res)
|
268
|
+
@conn.exec_params( "SELECT " + res.nfields.times.map{|i| "format_type($#{i*2+1},$#{i*2+2})"}.join(","),
|
269
|
+
res.nfields.times.map{|i| [res.ftype(i), res.fmod(i)] }.flatten ).
|
270
|
+
values[0]
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
# A matcher for checking the status of a PG::Connection to ensure it's still
|
275
|
+
# usable.
|
276
|
+
class ConnStillUsableMatcher
|
277
|
+
|
278
|
+
def initialize
|
279
|
+
@conn = nil
|
280
|
+
@problem = nil
|
281
|
+
end
|
282
|
+
|
283
|
+
def matches?( conn )
|
284
|
+
@conn = conn
|
285
|
+
@problem = self.check_for_problems
|
286
|
+
return @problem.nil?
|
287
|
+
end
|
288
|
+
|
289
|
+
def check_for_problems
|
290
|
+
return "is finished" if @conn.finished?
|
291
|
+
return "has bad status" unless @conn.status == PG::CONNECTION_OK
|
292
|
+
return "has bad transaction status (%d)" % [ @conn.transaction_status ] unless
|
293
|
+
@conn.transaction_status.between?( PG::PQTRANS_IDLE, PG::PQTRANS_INTRANS )
|
294
|
+
return "is not usable." unless self.can_exec_query?
|
295
|
+
return nil
|
296
|
+
end
|
297
|
+
|
298
|
+
def can_exec_query?
|
299
|
+
@conn.send_query( "VALUES (1)" )
|
300
|
+
@conn.get_last_result.values == [["1"]]
|
301
|
+
end
|
302
|
+
|
303
|
+
def failure_message
|
304
|
+
return "expected %p to be usable, but it %s" % [ @conn, @problem ]
|
305
|
+
end
|
306
|
+
|
307
|
+
def failure_message_when_negated
|
308
|
+
"expected %p not to be usable, but it still is" % [ @conn ]
|
309
|
+
end
|
310
|
+
|
311
|
+
end
|
312
|
+
|
313
|
+
|
314
|
+
### Return a ConnStillUsableMatcher to be used like:
|
315
|
+
###
|
316
|
+
### expect( pg_conn ).to still_be_usable
|
317
|
+
###
|
318
|
+
def still_be_usable
|
319
|
+
return ConnStillUsableMatcher.new
|
256
320
|
end
|
257
321
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
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
|
262
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
|
+
|
263
355
|
end
|
264
356
|
|
265
357
|
|
266
358
|
RSpec.configure do |config|
|
267
|
-
ruby_version_vec = RUBY_VERSION.split('.').map {|c| c.to_i }.pack( "N*" )
|
268
|
-
|
269
359
|
config.include( PG::TestingHelpers )
|
270
|
-
config.treat_symbols_as_metadata_keys_with_true_values = true
|
271
360
|
|
272
|
-
config.
|
273
|
-
config.
|
361
|
+
config.run_all_when_everything_filtered = true
|
362
|
+
config.filter_run :focus
|
363
|
+
config.order = 'random'
|
364
|
+
config.mock_with( :rspec ) do |mock|
|
365
|
+
mock.syntax = :expect
|
366
|
+
end
|
367
|
+
|
274
368
|
if RUBY_PLATFORM =~ /mingw|mswin/
|
275
369
|
config.filter_run_excluding :unix
|
276
370
|
else
|
277
371
|
config.filter_run_excluding :windows
|
278
372
|
end
|
279
|
-
config.filter_run_excluding :socket_io unless
|
280
|
-
PG::Connection.instance_methods.map( &:to_sym ).include?( :socket_io )
|
281
|
-
|
282
|
-
config.filter_run_excluding :postgresql_90 unless
|
283
|
-
PG::Connection.instance_methods.map( &:to_sym ).include?( :escape_literal )
|
284
|
-
|
285
|
-
if !PG.respond_to?( :library_version )
|
286
|
-
config.filter_run_excluding( :postgresql_91, :postgresql_92, :postgresql_93 )
|
287
|
-
elsif PG.library_version < 90200
|
288
|
-
config.filter_run_excluding( :postgresql_92, :postgresql_93 )
|
289
|
-
elsif PG.library_version < 90300
|
290
|
-
config.filter_run_excluding( :postgresql_93 )
|
291
|
-
end
|
292
|
-
end
|
293
373
|
|
374
|
+
config.filter_run_excluding( :postgresql_93 ) if PG.library_version < 90300
|
375
|
+
config.filter_run_excluding( :postgresql_94 ) if PG.library_version < 90400
|
376
|
+
config.filter_run_excluding( :postgresql_95 ) if PG.library_version < 90500
|
377
|
+
config.filter_run_excluding( :postgresql_96 ) if PG.library_version < 90600
|
378
|
+
config.filter_run_excluding( :postgresql_10 ) if PG.library_version < 100000
|
379
|
+
config.filter_run_excluding( :postgresql_12 ) if PG.library_version < 120000
|
380
|
+
end
|