pg 0.9.0.pre156-x86-mswin32

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
@@ -0,0 +1,291 @@
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
+ require 'timeout'
22
+
23
+ describe PGconn do
24
+ include PgTestingHelpers
25
+
26
+ before( :all ) do
27
+ @conn = setup_testing_db( "PGconn" )
28
+ end
29
+
30
+ before( :each ) do
31
+ @conn.exec( 'BEGIN' )
32
+ end
33
+
34
+
35
+ it "should connect successfully with connection string" do
36
+ tmpconn = PGconn.connect(@conninfo)
37
+ tmpconn.status.should== PGconn::CONNECTION_OK
38
+ tmpconn.finish
39
+ end
40
+
41
+ it "should connect using 7 arguments converted to strings" do
42
+ tmpconn = PGconn.connect('localhost', @port, nil, nil, :test, nil, nil)
43
+ tmpconn.status.should== PGconn::CONNECTION_OK
44
+ tmpconn.finish
45
+ end
46
+
47
+ it "should connect using hash" do
48
+ tmpconn = PGconn.connect(
49
+ :host => 'localhost',
50
+ :port => @port,
51
+ :dbname => :test)
52
+ tmpconn.status.should== PGconn::CONNECTION_OK
53
+ tmpconn.finish
54
+ end
55
+
56
+ it "should connect asynchronously" do
57
+ tmpconn = PGconn.connect_start(@conninfo)
58
+ socket = IO.for_fd(tmpconn.socket)
59
+ status = tmpconn.connect_poll
60
+ while(status != PGconn::PGRES_POLLING_OK) do
61
+ if(status == PGconn::PGRES_POLLING_READING)
62
+ if(not select([socket],[],[],5.0))
63
+ raise "Asynchronous connection timed out!"
64
+ end
65
+ elsif(status == PGconn::PGRES_POLLING_WRITING)
66
+ if(not select([],[socket],[],5.0))
67
+ raise "Asynchronous connection timed out!"
68
+ end
69
+ end
70
+ status = tmpconn.connect_poll
71
+ end
72
+ tmpconn.status.should== PGconn::CONNECTION_OK
73
+ tmpconn.finish
74
+ end
75
+
76
+ it "should not leave stale server connections after finish" do
77
+ PGconn.connect(@conninfo).finish
78
+ sleep 0.5
79
+ res = @conn.exec(%[SELECT COUNT(*) AS n FROM pg_stat_activity
80
+ WHERE usename IS NOT NULL])
81
+ # there's still the global @conn, but should be no more
82
+ res[0]['n'].should == '1'
83
+ end
84
+
85
+ unless RUBY_PLATFORM =~ /mswin|mingw/
86
+ it "should trace and untrace client-server communication" do
87
+ # be careful to explicitly close files so that the
88
+ # directory can be removed and we don't have to wait for
89
+ # 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
95
+ res = @conn.exec("SELECT 1 AS one")
96
+ @conn.untrace
97
+ res = @conn.exec("SELECT 2 AS two")
98
+ trace_file = open(File.join(@test_directory, "test_trace.out"), 'rb')
99
+ trace_data = trace_file.read
100
+ trace_file.close
101
+ trace_data.should == expected_trace_data
102
+ end
103
+ end
104
+
105
+ it "should cancel a query" do
106
+ error = false
107
+ @conn.send_query("SELECT pg_sleep(1000)")
108
+ @conn.cancel
109
+ tmpres = @conn.get_result
110
+ if(tmpres.result_status != PGresult::PGRES_TUPLES_OK)
111
+ error = true
112
+ end
113
+ error.should == true
114
+ end
115
+
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 )
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
184
+ end
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 )
290
+ end
291
+ end
@@ -0,0 +1,218 @@
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 PGresult do
23
+ include PgTestingHelpers
24
+
25
+ before( :all ) do
26
+ @conn = setup_testing_db( "PGresult" )
27
+ end
28
+
29
+ before( :each ) do
30
+ @conn.exec( 'BEGIN' )
31
+ end
32
+
33
+
34
+ it "should act as an array of hashes" do
35
+ res = @conn.exec("SELECT 1 AS a, 2 AS b")
36
+ res[0]['a'].should== '1'
37
+ res[0]['b'].should== '2'
38
+ end
39
+
40
+ it "should insert nil AS NULL and return NULL as nil" do
41
+ res = @conn.exec("SELECT $1::int AS n", [nil])
42
+ res[0]['n'].should == nil
43
+ end
44
+
45
+ it "should detect division by zero as SQLSTATE 22012" do
46
+ sqlstate = nil
47
+ begin
48
+ res = @conn.exec("SELECT 1/0")
49
+ rescue PGError => e
50
+ sqlstate = e.result.result_error_field(
51
+ PGresult::PG_DIAG_SQLSTATE).to_i
52
+ end
53
+ sqlstate.should == 22012
54
+ end
55
+
56
+ it "should return the same bytes in binary format that are sent in binary format" do
57
+ binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
58
+ bytes = File.open(binary_file, 'rb').read
59
+ res = @conn.exec('VALUES ($1::bytea)',
60
+ [ { :value => bytes, :format => 1 } ], 1)
61
+ res[0]['column1'].should== bytes
62
+ end
63
+
64
+ it "should return the same bytes in binary format that are sent as inline text" do
65
+ binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
66
+ in_bytes = File.open(binary_file, 'rb').read
67
+ out_bytes = nil
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
72
+ end
73
+
74
+ it "should return the same bytes in text format that are sent in binary format" do
75
+ binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
76
+ bytes = File.open(binary_file, 'rb').read
77
+ res = @conn.exec('VALUES ($1::bytea)',
78
+ [ { :value => bytes, :format => 1 } ])
79
+ PGconn.unescape_bytea(res[0]['column1']).should== bytes
80
+ end
81
+
82
+ it "should return the same bytes in text format that are sent as inline text" do
83
+ binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
84
+ in_bytes = File.open(binary_file, 'rb').read
85
+
86
+ out_bytes = nil
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' )
213
+ end
214
+
215
+ after( :all ) do
216
+ teardown_testing_db( @conn )
217
+ end
218
+ end