pg 0.9.0.pre156-x86-mswin32

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
@@ -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