pg 0.8.0 → 0.9.0.pre156

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.
@@ -0,0 +1,139 @@
1
+ #!/usr/bin/env spec
2
+ # encoding: utf-8
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ require 'rbconfig'
7
+
8
+ basedir = Pathname( __FILE__ ).dirname.parent
9
+ libdir = basedir + 'lib'
10
+ archlib = libdir + Config::CONFIG['sitearch']
11
+
12
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
+ $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
14
+ }
15
+
16
+ require 'pg'
17
+
18
+ require 'rubygems'
19
+ require 'spec'
20
+ require 'spec/lib/helpers'
21
+
22
+ describe "multinationalization support" do
23
+ include PgTestingHelpers
24
+
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
+ 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?
39
+ end
40
+
41
+
42
+ it "should return the same bytes in text format that are sent as inline text" do
43
+ binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
44
+ in_bytes = File.open(binary_file, 'r:ASCII-8BIT').read
45
+
46
+ out_bytes = nil
47
+ @conn.transaction do |conn|
48
+ conn.exec("SET standard_conforming_strings=on")
49
+ res = conn.exec("VALUES ('#{PGconn.escape_bytea(in_bytes)}'::bytea)", [], 0)
50
+ out_bytes = PGconn.unescape_bytea(res[0]['column1'])
51
+ end
52
+ out_bytes.should== in_bytes
53
+ end
54
+
55
+ describe "rubyforge #22925: m17n support" do
56
+ it "should return results in the same encoding as the client (iso-8859-1)" do
57
+ out_string = nil
58
+ @conn.transaction do |conn|
59
+ conn.internal_encoding = 'iso8859-1'
60
+ res = conn.exec("VALUES ('fantasia')", [], 0)
61
+ out_string = res[0]['column1']
62
+ end
63
+ out_string.should == 'fantasia'
64
+ out_string.encoding.should == Encoding::ISO8859_1
65
+ end
66
+
67
+ it "should return results in the same encoding as the client (utf-8)" do
68
+ out_string = nil
69
+ @conn.transaction do |conn|
70
+ conn.internal_encoding = 'utf-8'
71
+ res = conn.exec("VALUES ('世界線航跡蔵')", [], 0)
72
+ out_string = res[0]['column1']
73
+ end
74
+ out_string.should == '世界線航跡蔵'
75
+ out_string.encoding.should == Encoding::UTF_8
76
+ end
77
+
78
+ it "should return results in the same encoding as the client (EUC-JP)" do
79
+ out_string = nil
80
+ @conn.transaction do |conn|
81
+ conn.internal_encoding = 'EUC-JP'
82
+ stmt = "VALUES ('世界線航跡蔵')".encode('EUC-JP')
83
+ res = conn.exec(stmt, [], 0)
84
+ out_string = res[0]['column1']
85
+ end
86
+ out_string.should == '世界線航跡蔵'.encode('EUC-JP')
87
+ out_string.encoding.should == Encoding::EUC_JP
88
+ end
89
+
90
+ it "returns the results in the correct encoding even if the client_encoding has " +
91
+ "changed since the results were fetched" do
92
+ out_string = nil
93
+ @conn.transaction do |conn|
94
+ conn.internal_encoding = 'EUC-JP'
95
+ stmt = "VALUES ('世界線航跡蔵')".encode('EUC-JP')
96
+ res = conn.exec(stmt, [], 0)
97
+ conn.internal_encoding = 'utf-8'
98
+ out_string = res[0]['column1']
99
+ end
100
+ out_string.should == '世界線航跡蔵'.encode('EUC-JP')
101
+ out_string.encoding.should == Encoding::EUC_JP
102
+ end
103
+
104
+ it "the connection should return ASCII-8BIT when the server encoding is SQL_ASCII" do
105
+ @conn.external_encoding.should == Encoding::ASCII_8BIT
106
+ end
107
+
108
+ it "works around the unsupported JOHAB encoding by returning stuff in 'ASCII_8BIT'" do
109
+ pending "figuring out how to create a string in the JOHAB encoding" do
110
+ out_string = nil
111
+ @conn.transaction do |conn|
112
+ conn.exec( "set client_encoding = 'JOHAB';" )
113
+ stmt = "VALUES ('foo')".encode('JOHAB')
114
+ res = conn.exec( stmt, [], 0 )
115
+ out_string = res[0]['column1']
116
+ end
117
+ out_string.should == 'foo'.encode(Encoding::ASCII_8BIT)
118
+ out_string.encoding.should == Encoding::ASCII_8BIT
119
+ end
120
+ end
121
+
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)
126
+ escaped.encoding.should == Encoding::EUC_JP
127
+ end
128
+
129
+ end
130
+
131
+
132
+ after( :each ) do
133
+ @conn.exec( 'ROLLBACK' ) if @conn
134
+ end
135
+
136
+ after( :all ) do
137
+ teardown_testing_db( @conn ) if @conn
138
+ end
139
+ end
@@ -1,36 +1,37 @@
1
- require 'rubygems'
2
- require 'spec'
1
+ #!/usr/bin/env spec
2
+ # encoding: utf-8
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ require 'rbconfig'
7
+
8
+ basedir = Pathname( __FILE__ ).dirname.parent
9
+ libdir = basedir + 'lib'
10
+ archlib = libdir + Config::CONFIG['sitearch']
11
+
12
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
+ $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
14
+ }
3
15
 
4
- $LOAD_PATH.unshift('ext')
5
16
  require 'pg'
6
17
 
18
+ require 'rubygems'
19
+ require 'spec'
20
+ require 'spec/lib/helpers'
21
+ require 'timeout'
22
+
7
23
  describe PGconn do
24
+ include PgTestingHelpers
8
25
 
9
26
  before( :all ) do
10
- puts "====== TESTING PGconn ======"
11
- @test_directory = File.join(Dir.getwd, "tmp_test_#{rand}")
12
- @test_pgdata = File.join(@test_directory, 'data')
13
- if File.exists?(@test_directory) then
14
- raise "test directory exists!"
15
- end
16
- @port = 54321
17
- @conninfo = "host=localhost port=#{@port} dbname=test"
18
- Dir.mkdir(@test_directory)
19
- Dir.mkdir(@test_pgdata)
20
- cmds = []
21
- cmds << "initdb -D \"#{@test_pgdata}\""
22
- cmds << "pg_ctl -o \"-p #{@port}\" -D \"#{@test_pgdata}\" start"
23
- cmds << "sleep 5"
24
- cmds << "createdb -p #{@port} test"
25
-
26
- cmds.each do |cmd|
27
- if not system(cmd) then
28
- raise "Error executing cmd: #{cmd}: #{$?}"
29
- end
30
- end
31
- @conn = PGconn.connect(@conninfo)
27
+ @conn = setup_testing_db( "PGconn" )
28
+ end
29
+
30
+ before( :each ) do
31
+ @conn.exec( 'BEGIN' )
32
32
  end
33
33
 
34
+
34
35
  it "should connect successfully with connection string" do
35
36
  tmpconn = PGconn.connect(@conninfo)
36
37
  tmpconn.status.should== PGconn::CONNECTION_OK
@@ -86,7 +87,6 @@ describe PGconn do
86
87
  # be careful to explicitly close files so that the
87
88
  # directory can be removed and we don't have to wait for
88
89
  # the GC to run.
89
-
90
90
  expected_trace_file = File.join(Dir.getwd, "spec/data", "expected_trace.out")
91
91
  expected_trace_data = open(expected_trace_file, 'rb').read
92
92
  trace_file = open(File.join(@test_directory, "test_trace.out"), 'wb')
@@ -101,7 +101,7 @@ describe PGconn do
101
101
  trace_data.should == expected_trace_data
102
102
  end
103
103
  end
104
-
104
+
105
105
  it "should cancel a query" do
106
106
  error = false
107
107
  @conn.send_query("SELECT pg_sleep(1000)")
@@ -113,18 +113,179 @@ describe PGconn do
113
113
  error.should == true
114
114
  end
115
115
 
116
- after( :all ) do
117
- puts ""
118
- @conn.finish
119
- cmds = []
120
- cmds << "pg_ctl -D \"#{@test_pgdata}\" stop"
121
- cmds << "rm -rf \"#{@test_directory}\""
122
- cmds.each do |cmd|
123
- if not system(cmd) then
124
- raise "Error executing cmd: #{cmd}: #{$?}"
116
+ it "should not read past the end of a large object" do
117
+ @conn.transaction do
118
+ oid = @conn.lo_create( 0 )
119
+ fd = @conn.lo_open( oid, PGconn::INV_READ|PGconn::INV_WRITE )
120
+ @conn.lo_write( fd, "foobar" )
121
+ @conn.lo_read( fd, 10 ).should be_nil()
122
+ @conn.lo_lseek( fd, 0, PGconn::SEEK_SET )
123
+ @conn.lo_read( fd, 10 ).should == 'foobar'
124
+ end
125
+ end
126
+
127
+
128
+ it "should wait for NOTIFY events via select()" do
129
+ @conn.exec( 'ROLLBACK' )
130
+ @conn.exec( 'LISTEN woo' )
131
+
132
+ pid = fork do
133
+ conn = PGconn.connect( @conninfo )
134
+ sleep 1
135
+ conn.exec( 'NOTIFY woo' )
136
+ conn.finish
137
+ exit!
138
+ end
139
+
140
+ @conn.wait_for_notify( 10 ).should == 'woo'
141
+ @conn.exec( 'UNLISTEN woo' )
142
+
143
+ Process.wait( pid )
144
+ end
145
+
146
+ it "yields the result if block is given to exec" do
147
+ rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
148
+ values = []
149
+ result.should be_kind_of( PGresult )
150
+ result.ntuples.should == 2
151
+ result.each do |tuple|
152
+ values << tuple['a']
153
+ end
154
+ values
155
+ end
156
+
157
+ rval.should have( 2 ).members
158
+ rval.should include( '5678', '1234' )
159
+ end
160
+
161
+
162
+ it "correctly finishes COPY queries passed to #async_exec" do
163
+ @conn.async_exec( "COPY (SELECT 1 UNION ALL SELECT 2) TO STDOUT" )
164
+
165
+ results = []
166
+ begin
167
+ data = @conn.get_copy_data( true )
168
+ if false == data
169
+ @conn.block( 2.0 )
170
+ data = @conn.get_copy_data( true )
125
171
  end
172
+ results << data if data
173
+ end until data.nil?
174
+
175
+ results.should have( 2 ).members
176
+ results.should include( "1\n", "2\n" )
177
+ end
178
+
179
+
180
+ it "PGconn#block shouldn't block a second thread" do
181
+ t = Thread.new do
182
+ @conn.send_query( "select pg_sleep(3)" )
183
+ @conn.block
126
184
  end
127
- puts "====== COMPLETED TESTING PGconn ======"
128
- puts ""
185
+
186
+ # :FIXME: There's a race here, but hopefully it's pretty small.
187
+ t.should be_alive()
188
+
189
+ @conn.cancel
190
+ t.join
191
+ end
192
+
193
+ it "PGconn#block should allow a timeout" do
194
+ @conn.send_query( "select pg_sleep(3)" )
195
+
196
+ start = Time.now
197
+ @conn.block( 0.1 )
198
+ finish = Time.now
199
+
200
+ (finish - start).should be_close( 0.1, 0.05 )
201
+ end
202
+
203
+
204
+ it "can encrypt a string given a password and username" do
205
+ PGconn.encrypt_password("postgres", "postgres").
206
+ should =~ /\S+/
207
+ end
208
+
209
+
210
+ it "raises an appropriate error if either of the required arguments for encrypt_password " +
211
+ "is not valid" do
212
+ expect {
213
+ PGconn.encrypt_password( nil, nil )
214
+ }.to raise_error( TypeError )
215
+ expect {
216
+ PGconn.encrypt_password( "postgres", nil )
217
+ }.to raise_error( TypeError )
218
+ expect {
219
+ PGconn.encrypt_password( nil, "postgres" )
220
+ }.to raise_error( TypeError )
221
+ end
222
+
223
+
224
+ it "allows fetching a column of values from a result by column number" do
225
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
226
+ res.column_values( 0 ).should == %w[1 2 3]
227
+ res.column_values( 1 ).should == %w[2 3 4]
228
+ end
229
+
230
+
231
+ it "allows fetching a column of values from a result by field name" do
232
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
233
+ res.field_values( 'column1' ).should == %w[1 2 3]
234
+ res.field_values( 'column2' ).should == %w[2 3 4]
235
+ end
236
+
237
+
238
+ it "raises an error if selecting an invalid column index" do
239
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
240
+ expect {
241
+ res.column_values( 20 )
242
+ }.to raise_error( IndexError )
243
+ end
244
+
245
+
246
+ it "raises an error if selecting an invalid field name" do
247
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
248
+ expect {
249
+ res.field_values( 'hUUuurrg' )
250
+ }.to raise_error( IndexError )
251
+ end
252
+
253
+
254
+ it "raises an error if column index is not a number" do
255
+ res = @conn.exec( 'VALUES (1,2),(2,3),(3,4)' )
256
+ expect {
257
+ res.column_values( 'hUUuurrg' )
258
+ }.to raise_error( TypeError )
259
+ end
260
+
261
+
262
+ it "can connect asynchronously" do
263
+ serv = TCPServer.new( '127.0.0.1', 54320 )
264
+ conn = PGconn.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
265
+ conn.connect_poll.should == PGconn::PGRES_POLLING_WRITING
266
+ select( nil, [IO.for_fd(conn.socket)], nil, 0.2 )
267
+ serv.close
268
+ if conn.connect_poll == PGconn::PGRES_POLLING_READING
269
+ select( [IO.for_fd(conn.socket)], nil, nil, 0.2 )
270
+ end
271
+ conn.connect_poll.should == PGconn::PGRES_POLLING_FAILED
272
+ end
273
+
274
+ it "discards previous results (if any) before waiting on an #async_exec"
275
+
276
+ it "calls the block if one is provided to #async_exec" do
277
+ result = nil
278
+ @conn.async_exec( "select 47 as one" ) do |pg_res|
279
+ result = pg_res[0]
280
+ end
281
+ result.should == { 'one' => '47' }
282
+ end
283
+
284
+ after( :each ) do
285
+ @conn.exec( 'ROLLBACK' )
286
+ end
287
+
288
+ after( :all ) do
289
+ teardown_testing_db( @conn )
129
290
  end
130
291
  end
@@ -1,37 +1,36 @@
1
- require 'rubygems'
2
- require 'spec'
1
+ #!/usr/bin/env spec
2
+ # encoding: utf-8
3
+
4
+ BEGIN {
5
+ require 'pathname'
6
+ require 'rbconfig'
7
+
8
+ basedir = Pathname( __FILE__ ).dirname.parent
9
+ libdir = basedir + 'lib'
10
+ archlib = libdir + Config::CONFIG['sitearch']
11
+
12
+ $LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
13
+ $LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
14
+ }
3
15
 
4
- $LOAD_PATH.unshift('ext')
5
16
  require 'pg'
6
17
 
7
- describe PGconn do
18
+ require 'rubygems'
19
+ require 'spec'
20
+ require 'spec/lib/helpers'
21
+
22
+ describe PGresult do
23
+ include PgTestingHelpers
8
24
 
9
25
  before( :all ) do
10
- puts "====== TESTING PGresult ======"
11
- @test_directory = File.join(Dir.getwd, "tmp_test_#{rand}")
12
- @test_pgdata = File.join(@test_directory, 'data')
13
- if File.exists?(@test_directory) then
14
- raise "test directory exists!"
15
- end
16
- @port = 54321
17
- @conninfo = "host=localhost port=#{@port} dbname=test"
18
- Dir.mkdir(@test_directory)
19
- Dir.mkdir(@test_pgdata)
20
- cmds = []
21
- cmds << "initdb -D \"#{@test_pgdata}\""
22
- cmds << "pg_ctl -o \"-p #{@port}\" -D \"#{@test_pgdata}\" start"
23
- cmds << "sleep 5"
24
- cmds << "createdb -p #{@port} test"
25
-
26
- cmds.each do |cmd|
27
- if not system(cmd) then
28
- raise "Error executing cmd: #{cmd}: #{$?}"
29
- end
30
- end
31
- puts "\n\n"
32
- @conn = PGconn.connect(@conninfo)
26
+ @conn = setup_testing_db( "PGresult" )
27
+ end
28
+
29
+ before( :each ) do
30
+ @conn.exec( 'BEGIN' )
33
31
  end
34
32
 
33
+
35
34
  it "should act as an array of hashes" do
36
35
  res = @conn.exec("SELECT 1 AS a, 2 AS b")
37
36
  res[0]['a'].should== '1'
@@ -66,12 +65,10 @@ describe PGconn do
66
65
  binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
67
66
  in_bytes = File.open(binary_file, 'rb').read
68
67
  out_bytes = nil
69
- @conn.transaction do |conn|
70
- conn.exec("SET standard_conforming_strings=on")
71
- res = conn.exec("VALUES ('#{PGconn.escape_bytea(in_bytes)}'::bytea)", [], 1)
72
- out_bytes = res[0]['column1']
73
- end
74
- out_bytes.should== in_bytes
68
+ @conn.exec("SET standard_conforming_strings=on")
69
+ res = @conn.exec("VALUES ('#{PGconn.escape_bytea(in_bytes)}'::bytea)", [], 1)
70
+ out_bytes = res[0]['column1']
71
+ out_bytes.should == in_bytes
75
72
  end
76
73
 
77
74
  it "should return the same bytes in text format that are sent in binary format" do
@@ -87,26 +84,135 @@ describe PGconn do
87
84
  in_bytes = File.open(binary_file, 'rb').read
88
85
 
89
86
  out_bytes = nil
90
- @conn.transaction do |conn|
91
- conn.exec("SET standard_conforming_strings=on")
92
- res = conn.exec("VALUES ('#{PGconn.escape_bytea(in_bytes)}'::bytea)", [], 0)
93
- out_bytes = PGconn.unescape_bytea(res[0]['column1'])
94
- end
95
- out_bytes.should== in_bytes
87
+ @conn.exec("SET standard_conforming_strings=on")
88
+ res = @conn.exec("VALUES ('#{PGconn.escape_bytea(in_bytes)}'::bytea)", [], 0)
89
+ out_bytes = PGconn.unescape_bytea(res[0]['column1'])
90
+ out_bytes.should == in_bytes
91
+ end
92
+
93
+ it "should return the parameter type of the specified prepared statment parameter" do
94
+ query = 'SELECT * FROM pg_stat_activity WHERE user = $1::name AND current_query = $2::text'
95
+ @conn.prepare( 'queryfinder', query )
96
+ res = @conn.describe_prepared( 'queryfinder' )
97
+
98
+ @conn.exec( 'SELECT format_type($1, -1)', [res.paramtype(0)] ).getvalue( 0, 0 ).
99
+ should == 'name'
100
+ @conn.exec( 'SELECT format_type($1, -1)', [res.paramtype(1)] ).getvalue( 0, 0 ).
101
+ should == 'text'
102
+ end
103
+
104
+ it "should raise an exception when a negative index is given to #fformat" do
105
+ res = @conn.exec('SELECT * FROM pg_stat_activity')
106
+ expect {
107
+ res.fformat( -1 )
108
+ }.to raise_error( ArgumentError, /column number/i )
109
+ end
110
+
111
+ it "should raise an exception when a negative index is given to #fmod" do
112
+ res = @conn.exec('SELECT * FROM pg_stat_activity')
113
+ expect {
114
+ res.fmod( -1 )
115
+ }.to raise_error( ArgumentError, /column number/i )
116
+ end
117
+
118
+ it "should raise an exception when a negative index is given to #[]" do
119
+ res = @conn.exec('SELECT * FROM pg_stat_activity')
120
+ expect {
121
+ res[ -1 ]
122
+ }.to raise_error( IndexError, /-1 is out of range/i )
123
+ end
124
+
125
+ # PQfmod
126
+ it "can return the type modifier for a result column" do
127
+ @conn.exec( 'CREATE TABLE fmodtest ( foo varchar(33) )' )
128
+ res = @conn.exec( 'SELECT * FROM fmodtest' )
129
+ res.fmod( 0 ).should == 33 + 4 # Column length + varlena size (4)
130
+ end
131
+
132
+ it "should raise an exception when an invalid index is passed to PGresult#fmod" do
133
+ @conn.exec( 'CREATE TABLE fmodtest ( foo varchar(33) )' )
134
+ res = @conn.exec( 'SELECT * FROM fmodtest' )
135
+ expect { res.fmod(1) }.to raise_error( ArgumentError )
136
+ end
137
+
138
+ it "should raise an exception when an invalid (negative) index is passed to PGresult#fmod" do
139
+ @conn.exec( 'CREATE TABLE fmodtest ( foo varchar(33) )' )
140
+ res = @conn.exec( 'SELECT * FROM fmodtest' )
141
+ expect { res.fmod(-11) }.to raise_error( ArgumentError )
142
+ end
143
+
144
+ it "shouldn't raise an exception when a valid index is passed to PGresult#fmod for a column with no typemod" do
145
+ @conn.exec( 'CREATE TABLE fmodtest ( foo text )' )
146
+ res = @conn.exec( 'SELECT * FROM fmodtest' )
147
+ res.fmod( 0 ).should == -1 # and it shouldn't raise an exception, either
148
+ end
149
+
150
+ # PQftable
151
+ it "can return the oid of the table from which a result column was fetched" do
152
+ @conn.exec( 'CREATE TABLE ftabletest ( foo text )' )
153
+ res = @conn.exec( 'SELECT * FROM ftabletest' )
154
+
155
+ res.ftable( 0 ).should == be_nonzero()
156
+ end
157
+
158
+ it "should raise an exception when an invalid index is passed to PGresult#ftable" do
159
+ @conn.exec( 'CREATE TABLE ftabletest ( foo text )' )
160
+ res = @conn.exec( 'SELECT * FROM ftabletest' )
161
+
162
+ expect { res.ftable(18) }.to raise_error( ArgumentError )
163
+ end
164
+
165
+ it "should raise an exception when an invalid (negative) index is passed to PGresult#ftable" do
166
+ @conn.exec( 'CREATE TABLE ftabletest ( foo text )' )
167
+ res = @conn.exec( 'SELECT * FROM ftabletest' )
168
+
169
+ expect { res.ftable(-2) }.to raise_error( ArgumentError )
170
+ end
171
+
172
+ it "shouldn't raise an exception when a valid index is passed to PGresult#ftable for a " +
173
+ "column with no corresponding table" do
174
+ @conn.exec( 'CREATE TABLE ftabletest ( foo text )' )
175
+ res = @conn.exec( 'SELECT foo, LENGTH(foo) as length FROM ftabletest' )
176
+ res.ftable( 1 ).should == PGresult::InvalidOid # and it shouldn't raise an exception, either
177
+ end
178
+
179
+ # PQftablecol
180
+ it "can return the column number (within its table) of a column in a result" do
181
+ @conn.exec( 'CREATE TABLE ftablecoltest ( foo text, bar numeric )' )
182
+ res = @conn.exec( 'SELECT * FROM ftablecoltest' )
183
+
184
+ res.ftablecol( 0 ).should == 1
185
+ res.ftablecol( 1 ).should == 2
186
+ end
187
+
188
+ it "should raise an exception when an invalid index is passed to PGresult#ftablecol" do
189
+ @conn.exec( 'CREATE TABLE ftablecoltest ( foo text, bar numeric )' )
190
+ res = @conn.exec( 'SELECT * FROM ftablecoltest' )
191
+
192
+ expect { res.ftablecol(32) }.to raise_error( ArgumentError )
193
+ end
194
+
195
+ it "should raise an exception when an invalid (negative) index is passed to PGresult#ftablecol" do
196
+ @conn.exec( 'CREATE TABLE ftablecoltest ( foo text, bar numeric )' )
197
+ res = @conn.exec( 'SELECT * FROM ftablecoltest' )
198
+
199
+ expect { res.ftablecol(-1) }.to raise_error( ArgumentError )
200
+ end
201
+
202
+ it "shouldn't raise an exception when a valid index is passed to PGresult#ftablecol for a " +
203
+ "column with no corresponding table" do
204
+ @conn.exec( 'CREATE TABLE ftablecoltest ( foo text )' )
205
+ res = @conn.exec( 'SELECT foo, LENGTH(foo) as length FROM ftablecoltest' )
206
+ res.ftablecol(1).should == 0 # and it shouldn't raise an exception, either
207
+ end
208
+
209
+
210
+
211
+ after( :each ) do
212
+ @conn.exec( 'ROLLBACK' )
96
213
  end
97
214
 
98
215
  after( :all ) do
99
- puts ""
100
- @conn.finish
101
- cmds = []
102
- cmds << "pg_ctl -D \"#{@test_pgdata}\" stop"
103
- cmds << "rm -rf \"#{@test_directory}\""
104
- cmds.each do |cmd|
105
- if not system(cmd) then
106
- raise "Error executing cmd: #{cmd}: #{$?}"
107
- end
108
- end
109
- puts "====== COMPLETED TESTING PGresult ======"
110
- puts ""
216
+ teardown_testing_db( @conn )
111
217
  end
112
218
  end