pg 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,9 +1,19 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'pathname'
4
+ require 'rspec'
5
+
6
+
7
+ RSpec.configure do |config|
8
+ ruby_version_vec = RUBY_VERSION.split('.').map {|c| c.to_i }.pack( "N*" )
9
+
10
+ config.mock_with :rspec
11
+ config.filter_run_excluding :ruby_19 => true if ruby_version_vec <= [1,9,1].pack( "N*" )
12
+ end
4
13
 
5
14
  module PgTestingHelpers
6
15
 
16
+
7
17
  # Set some ANSI escape code constants (Shamelessly stolen from Perl's
8
18
  # Term::ANSIColor by Russ Allbery <rra@stanford.edu> and Zenin <zenin@best.com>
9
19
  ANSI_ATTRIBUTES = {
@@ -104,6 +114,8 @@ module PgTestingHelpers
104
114
  end
105
115
 
106
116
 
117
+ NOFORK_PLATFORMS = %w{java}
118
+
107
119
  ### Run the specified command +cmd+ after redirecting stdout and stderr to the specified
108
120
  ### +logpath+, failing if the execution fails.
109
121
  def log_and_run( logpath, *cmd )
@@ -115,16 +127,24 @@ module PgTestingHelpers
115
127
  trace( cmd )
116
128
  end
117
129
 
118
- logfh = File.open( logpath, File::WRONLY|File::CREAT|File::APPEND )
119
- if pid = fork
120
- logfh.close
121
- Process.wait
130
+ # Eliminate the noise of creating/tearing down the database by
131
+ # redirecting STDERR/STDOUT to a logfile if the Ruby interpreter
132
+ # supports fork()
133
+ if NOFORK_PLATFORMS.include?( RUBY_PLATFORM )
134
+ system( *cmd )
122
135
  else
123
- $stdout.reopen( logfh )
124
- $stderr.reopen( $stdout )
125
- exec( *cmd )
126
- $stderr.puts "After the exec()?!??!"
127
- exit!
136
+ logfh = File.open( logpath, File::WRONLY|File::CREAT|File::APPEND )
137
+ if pid = fork
138
+ logfh.close
139
+ else
140
+ $stdout.reopen( logfh )
141
+ $stderr.reopen( $stdout )
142
+ exec( *cmd )
143
+ $stderr.puts "After the exec()?!??!"
144
+ exit!
145
+ end
146
+
147
+ Process.wait( pid )
128
148
  end
129
149
 
130
150
  raise "Command failed: [%s]" % [cmd.join(' ')] unless $?.success?
@@ -147,7 +167,7 @@ module PgTestingHelpers
147
167
  trace "No postmaster running for %s" % [ datadir ]
148
168
  # Process isn't alive, so don't try to stop it
149
169
  else
150
- trace "Stopping lingering database at PID %d"
170
+ trace "Stopping lingering database at PID %d" % [ pid ]
151
171
  run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
152
172
  end
153
173
  end
@@ -9,33 +9,21 @@ BEGIN {
9
9
  libdir = basedir + 'lib'
10
10
  archlib = libdir + Config::CONFIG['sitearch']
11
11
 
12
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
12
13
  $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
14
  $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
14
15
  }
15
16
 
16
- require 'pg'
17
-
18
- require 'rubygems'
19
- require 'spec'
17
+ require 'rspec'
20
18
  require 'spec/lib/helpers'
19
+ require 'pg'
21
20
 
22
- describe "multinationalization support" do
21
+ describe "multinationalization support", :ruby_19 => true do
23
22
  include PgTestingHelpers
24
23
 
25
- RUBY_VERSION_VEC = RUBY_VERSION.split('.').map {|c| c.to_i }.pack("N*")
26
- MIN_RUBY_VERSION_VEC = [1,9,1].pack('N*')
27
-
28
-
29
24
  before( :all ) do
30
- @conn = nil
31
- if RUBY_VERSION_VEC >= MIN_RUBY_VERSION_VEC
32
- @conn = setup_testing_db( "m17n" )
33
- @conn.exec( 'BEGIN' )
34
- end
35
- end
36
-
37
- before( :each ) do
38
- pending "depends on m17n support in Ruby >= 1.9.1" if @conn.nil?
25
+ @conn = setup_testing_db( "m17n" )
26
+ @conn.exec( 'BEGIN' )
39
27
  end
40
28
 
41
29
 
@@ -49,7 +37,7 @@ describe "multinationalization support" do
49
37
  res = conn.exec("VALUES ('#{PGconn.escape_bytea(in_bytes)}'::bytea)", [], 0)
50
38
  out_bytes = PGconn.unescape_bytea(res[0]['column1'])
51
39
  end
52
- out_bytes.should== in_bytes
40
+ out_bytes.should == in_bytes
53
41
  end
54
42
 
55
43
  describe "rubyforge #22925: m17n support" do
@@ -114,17 +102,41 @@ describe "multinationalization support" do
114
102
  res = conn.exec( stmt, [], 0 )
115
103
  out_string = res[0]['column1']
116
104
  end
117
- out_string.should == 'foo'.encode(Encoding::ASCII_8BIT)
105
+ out_string.should == 'foo'.encode( Encoding::ASCII_8BIT )
118
106
  out_string.encoding.should == Encoding::ASCII_8BIT
119
107
  end
120
108
  end
121
109
 
122
- it "should use client encoding for escaped string" do
123
- original = "string to escape".force_encoding("euc-jp")
124
- @conn.set_client_encoding("euc_jp")
125
- escaped = @conn.escape(original)
110
+ it "uses the client encoding for escaped string" do
111
+ original = "string to escape".force_encoding( "euc-jp" )
112
+ @conn.set_client_encoding( "euc_jp" )
113
+ escaped = @conn.escape( original )
126
114
  escaped.encoding.should == Encoding::EUC_JP
127
115
  end
116
+ end
117
+
118
+ describe "Ruby 1.9.x default_internal encoding" do
119
+
120
+ it "honors the Encoding.default_internal if it's set and the synchronous interface is used" do
121
+ @conn.transaction do |txn_conn|
122
+ txn_conn.internal_encoding = Encoding::ISO8859_1
123
+ txn_conn.exec( "CREATE TABLE defaultinternaltest ( foo text )" )
124
+ txn_conn.exec( "INSERT INTO defaultinternaltest VALUES ('Grün und Weiß')" )
125
+ end
126
+
127
+ begin
128
+ prev_encoding = Encoding.default_internal
129
+ Encoding.default_internal = Encoding::UTF_8
130
+
131
+ conn = PGconn.connect( @conninfo )
132
+ conn.internal_encoding.should == Encoding::UTF_8
133
+ res = conn.exec( "SELECT foo FROM defaultinternaltest" )
134
+ res[0]['foo'].encoding.should == Encoding::UTF_8
135
+ ensure
136
+ conn.finish if conn
137
+ Encoding.default_internal = prev_encoding
138
+ end
139
+ end
128
140
 
129
141
  end
130
142
 
@@ -9,15 +9,14 @@ BEGIN {
9
9
  libdir = basedir + 'lib'
10
10
  archlib = libdir + Config::CONFIG['sitearch']
11
11
 
12
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
12
13
  $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
14
  $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
14
15
  }
15
16
 
16
- require 'pg'
17
-
18
- require 'rubygems'
19
- require 'spec'
17
+ require 'rspec'
20
18
  require 'spec/lib/helpers'
19
+ require 'pg'
21
20
  require 'timeout'
22
21
 
23
22
  describe PGconn do
@@ -82,27 +81,69 @@ describe PGconn do
82
81
  res[0]['n'].should == '1'
83
82
  end
84
83
 
84
+
85
+ EXPECTED_TRACE_OUTPUT = %{
86
+ To backend> Msg Q
87
+ To backend> "SELECT 1 AS one"
88
+ To backend> Msg complete, length 21
89
+ From backend> T
90
+ From backend (#4)> 28
91
+ From backend (#2)> 1
92
+ From backend> "one"
93
+ From backend (#4)> 0
94
+ From backend (#2)> 0
95
+ From backend (#4)> 23
96
+ From backend (#2)> 4
97
+ From backend (#4)> -1
98
+ From backend (#2)> 0
99
+ From backend> D
100
+ From backend (#4)> 11
101
+ From backend (#2)> 1
102
+ From backend (#4)> 1
103
+ From backend (1)> 1
104
+ From backend> C
105
+ From backend (#4)> 13
106
+ From backend> "SELECT 1"
107
+ From backend> Z
108
+ From backend (#4)> 5
109
+ From backend> Z
110
+ From backend (#4)> 5
111
+ From backend> T
112
+ }.gsub( /^\t{2}/, '' ).lstrip
113
+
85
114
  unless RUBY_PLATFORM =~ /mswin|mingw/
86
115
  it "should trace and untrace client-server communication" do
87
116
  # be careful to explicitly close files so that the
88
117
  # directory can be removed and we don't have to wait for
89
118
  # the GC to run.
90
- expected_trace_file = File.join(Dir.getwd, "spec/data", "expected_trace.out")
91
- expected_trace_data = open(expected_trace_file, 'rb').read
92
- trace_file = open(File.join(@test_directory, "test_trace.out"), 'wb')
93
- @conn.trace(trace_file)
94
- trace_file.close
119
+ trace_file = @test_directory + "test_trace.out"
120
+ trace_io = trace_file.open( 'w', 0600 )
121
+ @conn.trace( trace_io )
122
+ trace_io.close
123
+
95
124
  res = @conn.exec("SELECT 1 AS one")
96
125
  @conn.untrace
126
+
97
127
  res = @conn.exec("SELECT 2 AS two")
98
- trace_file = open(File.join(@test_directory, "test_trace.out"), 'rb')
128
+
99
129
  trace_data = trace_file.read
100
- trace_file.close
101
- trace_data.should == expected_trace_data
130
+
131
+ expected_trace_output = EXPECTED_TRACE_OUTPUT.dup
132
+ # For PostgreSQL < 9.0, the output will be different:
133
+ # -From backend (#4)> 13
134
+ # -From backend> "SELECT 1"
135
+ # +From backend (#4)> 11
136
+ # +From backend> "SELECT"
137
+ if @conn.server_version < 90000
138
+ expected_trace_output.sub!( /From backend \(#4\)> 13/, 'From backend (#4)> 11' )
139
+ expected_trace_output.sub!( /From backend> "SELECT 1"/, 'From backend> "SELECT"' )
140
+ end
141
+
142
+ trace_data.should == expected_trace_output
102
143
  end
103
144
  end
104
145
 
105
- it "should cancel a query" do
146
+ it "allows a query to be cancelled" do
106
147
  error = false
107
148
  @conn.send_query("SELECT pg_sleep(1000)")
108
149
  @conn.cancel
@@ -113,6 +154,25 @@ describe PGconn do
113
154
  error.should == true
114
155
  end
115
156
 
157
+ it "automatically rolls back a transaction started with PGconn#transaction if an exception " +
158
+ "is raised" do
159
+ # abort the per-example transaction so we can test our own
160
+ @conn.exec( 'ROLLBACK' )
161
+
162
+ res = nil
163
+ @conn.exec( "CREATE TABLE pie ( flavor TEXT )" )
164
+
165
+ expect {
166
+ res = @conn.transaction do
167
+ @conn.exec( "INSERT INTO pie VALUES ('rhubarb'), ('cherry'), ('schizophrenia')" )
168
+ raise "Oh noes! All pie is gone!"
169
+ end
170
+ }.to raise_exception( RuntimeError, /all pie is gone/i )
171
+
172
+ res = @conn.exec( "SELECT * FROM pie" )
173
+ res.ntuples.should == 0
174
+ end
175
+
116
176
  it "should not read past the end of a large object" do
117
177
  @conn.transaction do
118
178
  oid = @conn.lo_create( 0 )
@@ -125,16 +185,19 @@ describe PGconn do
125
185
  end
126
186
 
127
187
 
128
- it "should wait for NOTIFY events via select()" do
188
+ it "can wait for NOTIFY events" do
129
189
  @conn.exec( 'ROLLBACK' )
130
190
  @conn.exec( 'LISTEN woo' )
131
191
 
132
192
  pid = fork do
133
- conn = PGconn.connect( @conninfo )
134
- sleep 1
135
- conn.exec( 'NOTIFY woo' )
136
- conn.finish
137
- exit!
193
+ begin
194
+ conn = PGconn.connect( @conninfo )
195
+ sleep 1
196
+ conn.exec( 'NOTIFY woo' )
197
+ ensure
198
+ conn.finish
199
+ exit!
200
+ end
138
201
  end
139
202
 
140
203
  @conn.wait_for_notify( 10 ).should == 'woo'
@@ -143,6 +206,89 @@ describe PGconn do
143
206
  Process.wait( pid )
144
207
  end
145
208
 
209
+ it "calls a block for NOTIFY events if one is given" do
210
+ @conn.exec( 'ROLLBACK' )
211
+ @conn.exec( 'LISTEN woo' )
212
+
213
+ pid = fork do
214
+ begin
215
+ conn = PGconn.connect( @conninfo )
216
+ sleep 1
217
+ conn.exec( 'NOTIFY woo' )
218
+ ensure
219
+ conn.finish
220
+ exit!
221
+ end
222
+ end
223
+
224
+ eventpid = event = nil
225
+ @conn.wait_for_notify( 10 ) {|*args| event, eventpid = args }
226
+ event.should == 'woo'
227
+ eventpid.should be_an( Integer )
228
+
229
+ @conn.exec( 'UNLISTEN woo' )
230
+
231
+ Process.wait( pid )
232
+ end
233
+
234
+ it "doesn't collapse sequential notifications" do
235
+ @conn.exec( 'ROLLBACK' )
236
+ @conn.exec( 'LISTEN woo' )
237
+ @conn.exec( 'LISTEN war' )
238
+ @conn.exec( 'LISTEN woz' )
239
+
240
+ pid = fork do
241
+ begin
242
+ conn = PGconn.connect( @conninfo )
243
+ conn.exec( 'NOTIFY woo' )
244
+ conn.exec( 'NOTIFY war' )
245
+ conn.exec( 'NOTIFY woz' )
246
+ ensure
247
+ conn.finish
248
+ exit!
249
+ end
250
+ end
251
+
252
+ Process.wait( pid )
253
+
254
+ channels = []
255
+ 3.times do
256
+ channels << @conn.wait_for_notify( 2 )
257
+ end
258
+
259
+ channels.should have( 3 ).members
260
+ channels.should include( 'woo', 'war', 'woz' )
261
+
262
+ @conn.exec( 'UNLISTEN woz' )
263
+ @conn.exec( 'UNLISTEN war' )
264
+ @conn.exec( 'UNLISTEN woo' )
265
+ end
266
+
267
+ it "returns notifications which are already in the queue before wait_for_notify is called " +
268
+ "without waiting for the socket to become readable" do
269
+ @conn.exec( 'ROLLBACK' )
270
+ @conn.exec( 'LISTEN woo' )
271
+
272
+ pid = fork do
273
+ begin
274
+ conn = PGconn.connect( @conninfo )
275
+ conn.exec( 'NOTIFY woo' )
276
+ ensure
277
+ conn.finish
278
+ exit!
279
+ end
280
+ end
281
+
282
+ # Wait for the forked child to send the notification
283
+ Process.wait( pid )
284
+
285
+ # Cause the notification to buffer, but not be read yet
286
+ @conn.exec( 'SELECT 1' )
287
+
288
+ @conn.wait_for_notify( 10 ).should == 'woo'
289
+ @conn.exec( 'UNLISTEN woo' )
290
+ end
291
+
146
292
  it "yields the result if block is given to exec" do
147
293
  rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
148
294
  values = []
@@ -9,15 +9,14 @@ BEGIN {
9
9
  libdir = basedir + 'lib'
10
10
  archlib = libdir + Config::CONFIG['sitearch']
11
11
 
12
+ $LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
12
13
  $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
14
  $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
14
15
  }
15
16
 
16
- require 'pg'
17
-
18
- require 'rubygems'
19
- require 'spec'
17
+ require 'rspec'
20
18
  require 'spec/lib/helpers'
19
+ require 'pg'
21
20
 
22
21
  describe PGresult do
23
22
  include PgTestingHelpers
@@ -206,8 +205,6 @@ describe PGresult do
206
205
  res.ftablecol(1).should == 0 # and it shouldn't raise an exception, either
207
206
  end
208
207
 
209
-
210
-
211
208
  after( :each ) do
212
209
  @conn.exec( 'ROLLBACK' )
213
210
  end
metadata CHANGED
@@ -1,15 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ hash: 55
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 10
9
+ - 0
10
+ version: 0.10.0
5
11
  platform: ruby
6
12
  authors:
13
+ - Jeff Davis
7
14
  - Michael Granger
8
15
  autorequire:
9
16
  bindir: bin
10
- cert_chain: []
17
+ cert_chain:
18
+ - |
19
+ -----BEGIN CERTIFICATE-----
20
+ MIIDLDCCAhSgAwIBAgIBADANBgkqhkiG9w0BAQUFADA8MQwwCgYDVQQDDANnZWQx
21
+ FzAVBgoJkiaJk/IsZAEZFgdfYWVyaWVfMRMwEQYKCZImiZPyLGQBGRYDb3JnMB4X
22
+ DTEwMDkxNjE0NDg1MVoXDTExMDkxNjE0NDg1MVowPDEMMAoGA1UEAwwDZ2VkMRcw
23
+ FQYKCZImiZPyLGQBGRYHX2FlcmllXzETMBEGCgmSJomT8ixkARkWA29yZzCCASIw
24
+ DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALy//BFxC1f/cPSnwtJBWoFiFrir
25
+ h7RicI+joq/ocVXQqI4TDWPyF/8tqkvt+rD99X9qs2YeR8CU/YiIpLWrQOYST70J
26
+ vDn7Uvhb2muFVqq6+vobeTkILBEO6pionWDG8jSbo3qKm1RjKJDwg9p4wNKhPuu8
27
+ KGue/BFb67KflqyApPmPeb3Vdd9clspzqeFqp7cUBMEpFS6LWxy4Gk+qvFFJBJLB
28
+ BUHE/LZVJMVzfpC5Uq+QmY7B+FH/QqNndn3tOHgsPadLTNimuB1sCuL1a4z3Pepd
29
+ TeLBEFmEao5Dk3K/Q8o8vlbIB/jBDTUx6Djbgxw77909x6gI9doU4LD5XMcCAwEA
30
+ AaM5MDcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFJeoGkOr9l4B
31
+ +saMkW/ZXT4UeSvVMA0GCSqGSIb3DQEBBQUAA4IBAQBG2KObvYI2eHyyBUJSJ3jN
32
+ vEnU3d60znAXbrSd2qb3r1lY1EPDD3bcy0MggCfGdg3Xu54z21oqyIdk8uGtWBPL
33
+ HIa9EgfFGSUEgvcIvaYqiN4jTUtidfEFw+Ltjs8AP9gWgSIYS6Gr38V0WGFFNzIH
34
+ aOD2wmu9oo/RffW4hS/8GuvfMzcw7CQ355wFR4KB/nyze+EsZ1Y5DerCAagMVuDQ
35
+ U0BLmWDFzPGGWlPeQCrYHCr+AcJz+NRnaHCKLZdSKj/RHuTOt+gblRex8FAh8NeA
36
+ cmlhXe46pZNJgWKbxZah85jIjx95hR8vOI+NAM5iH9kOqK13DrxacTKPhqj5PjwF
37
+ -----END CERTIFICATE-----
11
38
 
12
- date: 2010-02-28 00:00:00 -08:00
39
+ date: 2010-12-01 00:00:00 -08:00
13
40
  default_executable:
14
41
  dependencies: []
15
42
 
@@ -17,6 +44,7 @@ description: |-
17
44
  This is the extension library to access a PostgreSQL database from Ruby.
18
45
  This library works with PostgreSQL 7.4 and later.
19
46
  email:
47
+ - ruby-pg@j-davis.com
20
48
  - ged@FaerieMUD.org
21
49
  executables: []
22
50
 
@@ -25,11 +53,17 @@ extensions:
25
53
  extra_rdoc_files:
26
54
  - ChangeLog
27
55
  - README
56
+ - README.ja
57
+ - README.OS_X
58
+ - README.windows
28
59
  - LICENSE
29
60
  files:
30
61
  - Rakefile
31
62
  - ChangeLog
32
63
  - README
64
+ - README.ja
65
+ - README.OS_X
66
+ - README.windows
33
67
  - LICENSE
34
68
  - spec/m17n_spec.rb
35
69
  - spec/pgconn_spec.rb
@@ -43,12 +77,12 @@ files:
43
77
  - ext/extconf.rb
44
78
  - rake/191_compat.rb
45
79
  - rake/dependencies.rb
80
+ - rake/documentation.rb
46
81
  - rake/helpers.rb
47
82
  - rake/hg.rb
48
83
  - rake/manual.rb
49
84
  - rake/packaging.rb
50
85
  - rake/publishing.rb
51
- - rake/rdoc.rb
52
86
  - rake/style.rb
53
87
  - rake/svn.rb
54
88
  - rake/testing.rb
@@ -60,42 +94,49 @@ files:
60
94
  - ./BSD
61
95
  - ./Contributors
62
96
  - Rakefile.local
97
+ - spec/data/expected_trace.out
98
+ - spec/data/random_binary_data
63
99
  has_rdoc: true
64
100
  homepage: http://bitbucket.org/ged/ruby-pg/
65
- licenses: []
66
-
101
+ licenses:
102
+ - Ruby
103
+ - GPL
104
+ - BSD
67
105
  post_install_message:
68
106
  rdoc_options:
69
- - -w
70
- - "4"
71
- - -HN
72
- - -i
107
+ - --tab-width=4
108
+ - --show-hash
109
+ - --include
73
110
  - .
74
- - -m
75
- - README
76
- - -t
77
- - pg
78
- - -W
79
- - http://bitbucket.org/ged/ruby-pg/browser/
111
+ - --main=README
112
+ - --title=pg
80
113
  require_paths:
81
114
  - lib
82
115
  - ext
83
116
  required_ruby_version: !ruby/object:Gem::Requirement
117
+ none: false
84
118
  requirements:
85
119
  - - ">="
86
120
  - !ruby/object:Gem::Version
87
- version: "0"
88
- version:
121
+ hash: 57
122
+ segments:
123
+ - 1
124
+ - 8
125
+ - 7
126
+ version: 1.8.7
89
127
  required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
90
129
  requirements:
91
130
  - - ">="
92
131
  - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
93
135
  version: "0"
94
- version:
95
136
  requirements:
96
137
  - PostgreSQL >=7.4
97
138
  rubyforge_project:
98
- rubygems_version: 1.3.5
139
+ rubygems_version: 1.3.7
99
140
  signing_key:
100
141
  specification_version: 3
101
142
  summary: A Ruby interface to the PostgreSQL RDBMS