pg 0.8.0 → 0.9.0.pre156

Sign up to get free protection for your applications and to get access to all the features.
@@ -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