pg 0.12.2 → 0.13.0.pre298
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.hoerc +2 -0
- data/.tm_properties +12 -0
- data/ChangeLog +86 -6
- data/Contributors.rdoc +7 -0
- data/History.rdoc +29 -0
- data/LICENSE +12 -14
- data/Manifest.txt +15 -14
- data/{BSD → POSTGRES} +0 -0
- data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
- data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
- data/README.ja.rdoc +1 -1
- data/README.rdoc +39 -27
- data/Rakefile +1 -2
- data/ext/extconf.rb +9 -2
- data/ext/pg.c +232 -4297
- data/ext/pg.h +87 -23
- data/ext/pg_connection.c +3301 -0
- data/ext/pg_result.c +905 -0
- data/lib/pg.rb +26 -43
- data/lib/pg/connection.rb +58 -0
- data/lib/pg/constants.rb +11 -0
- data/lib/pg/exceptions.rb +11 -0
- data/lib/pg/result.rb +11 -0
- data/misc/openssl-pg-segfault.rb +1 -1
- data/sample/async_api.rb +16 -21
- data/sample/async_copyto.rb +1 -1
- data/sample/async_mixed.rb +56 -0
- data/sample/copyfrom.rb +1 -1
- data/sample/copyto.rb +1 -1
- data/sample/cursor.rb +1 -1
- data/sample/losample.rb +6 -6
- data/sample/notify_wait.rb +51 -22
- data/sample/test_binary_values.rb +4 -6
- data/spec/lib/helpers.rb +14 -10
- data/spec/{pgconn_spec.rb → pg/connection_spec.rb} +227 -60
- data/spec/{pgresult_spec.rb → pg/result_spec.rb} +31 -35
- data/spec/pg_spec.rb +22 -0
- metadata +44 -42
- metadata.gz.sig +0 -0
- data/GPL +0 -340
- data/ext/compat.c +0 -541
- data/ext/compat.h +0 -184
- data/sample/psql.rb +0 -1181
- data/sample/psqlHelp.rb +0 -158
- data/sample/test1.rb +0 -60
- data/sample/test2.rb +0 -44
- data/sample/test4.rb +0 -71
- data/spec/m17n_spec.rb +0 -170
@@ -2,18 +2,16 @@
|
|
2
2
|
|
3
3
|
require 'pg'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
db = PGconn.connect( connhash )
|
5
|
+
db = PG.connect( :dbname => 'test' )
|
8
6
|
db.exec "DROP TABLE IF EXISTS test"
|
9
7
|
db.exec "CREATE TABLE test (a INTEGER, b BYTEA)"
|
10
8
|
|
11
9
|
a = 42
|
12
10
|
b = [1, 2, 3]
|
13
|
-
db.exec "INSERT INTO test(a, b) VALUES($1::int, $2::bytea)",
|
14
|
-
[a, {:value => b.pack('N*'), :format => 1}]
|
11
|
+
db.exec "INSERT INTO test(a, b) VALUES($1::int, $2::bytea)",
|
12
|
+
[a, {:value => b.pack('N*'), :format => 1}]
|
15
13
|
|
16
|
-
db.exec "SELECT a::int, b::bytea FROM test LIMIT 1", [], 1 do |res|
|
14
|
+
db.exec( "SELECT a::int, b::bytea FROM test LIMIT 1", [], 1 ) do |res|
|
17
15
|
|
18
16
|
res.nfields.times do |i|
|
19
17
|
puts "Field %d is: %s, a %s (%s) column from table %p" % [
|
data/spec/lib/helpers.rb
CHANGED
@@ -3,17 +3,11 @@
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'rspec'
|
5
5
|
require 'shellwords'
|
6
|
+
require 'pg'
|
6
7
|
|
7
8
|
TEST_DIRECTORY = Pathname.getwd + "tmp_test_specs"
|
8
9
|
|
9
|
-
|
10
|
-
ruby_version_vec = RUBY_VERSION.split('.').map {|c| c.to_i }.pack( "N*" )
|
11
|
-
|
12
|
-
config.mock_with :rspec
|
13
|
-
config.filter_run_excluding :ruby_19 => true if ruby_version_vec <= [1,9,1].pack( "N*" )
|
14
|
-
end
|
15
|
-
|
16
|
-
module PgTestingHelpers
|
10
|
+
module PG::TestingHelpers
|
17
11
|
|
18
12
|
|
19
13
|
# Set some ANSI escape code constants (Shamelessly stolen from Perl's
|
@@ -202,7 +196,7 @@ module PgTestingHelpers
|
|
202
196
|
unless (@test_pgdata+"postgresql.conf").exist?
|
203
197
|
FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
|
204
198
|
$stderr.puts "Running initdb"
|
205
|
-
log_and_run @logfile, 'initdb', '--no-locale', '-D', @test_pgdata.to_s
|
199
|
+
log_and_run @logfile, 'initdb', '-E', 'UTF8', '--no-locale', '-D', @test_pgdata.to_s
|
206
200
|
end
|
207
201
|
|
208
202
|
trace "Starting postgres"
|
@@ -221,7 +215,7 @@ module PgTestingHelpers
|
|
221
215
|
fail
|
222
216
|
end
|
223
217
|
|
224
|
-
conn =
|
218
|
+
conn = PG.connect( @conninfo )
|
225
219
|
conn.set_notice_processor do |message|
|
226
220
|
$stderr.puts( message ) if $DEBUG
|
227
221
|
end
|
@@ -238,3 +232,13 @@ module PgTestingHelpers
|
|
238
232
|
end
|
239
233
|
|
240
234
|
|
235
|
+
RSpec.configure do |config|
|
236
|
+
ruby_version_vec = RUBY_VERSION.split('.').map {|c| c.to_i }.pack( "N*" )
|
237
|
+
|
238
|
+
config.include( PG::TestingHelpers )
|
239
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
240
|
+
|
241
|
+
config.mock_with :rspec
|
242
|
+
config.filter_run_excluding :ruby_19 => true if ruby_version_vec <= [1,9,1].pack( "N*" )
|
243
|
+
end
|
244
|
+
|
@@ -1,38 +1,33 @@
|
|
1
1
|
#!/usr/bin/env rspec
|
2
|
-
#
|
2
|
+
#encoding: utf-8
|
3
3
|
|
4
4
|
BEGIN {
|
5
5
|
require 'pathname'
|
6
|
-
require 'rbconfig'
|
7
6
|
|
8
|
-
basedir = Pathname( __FILE__ ).dirname.parent
|
7
|
+
basedir = Pathname( __FILE__ ).dirname.parent.parent
|
9
8
|
libdir = basedir + 'lib'
|
10
|
-
archlib = libdir + Config::CONFIG['sitearch']
|
11
9
|
|
12
10
|
$LOAD_PATH.unshift( basedir.to_s ) unless $LOAD_PATH.include?( basedir.to_s )
|
13
11
|
$LOAD_PATH.unshift( libdir.to_s ) unless $LOAD_PATH.include?( libdir.to_s )
|
14
|
-
$LOAD_PATH.unshift( archlib.to_s ) unless $LOAD_PATH.include?( archlib.to_s )
|
15
12
|
}
|
16
13
|
|
17
14
|
require 'rspec'
|
18
15
|
require 'spec/lib/helpers'
|
19
|
-
require 'pg'
|
20
16
|
require 'timeout'
|
17
|
+
require 'pg'
|
21
18
|
|
22
|
-
describe
|
23
|
-
include PgTestingHelpers
|
24
|
-
|
19
|
+
describe PG::Connection do
|
25
20
|
|
26
21
|
before( :all ) do
|
27
|
-
@conn = setup_testing_db( "
|
22
|
+
@conn = setup_testing_db( "PG_Connection" )
|
28
23
|
end
|
29
24
|
|
30
25
|
before( :each ) do
|
31
|
-
@conn.exec( 'BEGIN' )
|
26
|
+
@conn.exec( 'BEGIN' ) unless example.metadata[:without_transaction]
|
32
27
|
end
|
33
28
|
|
34
29
|
after( :each ) do
|
35
|
-
@conn.exec( 'ROLLBACK' )
|
30
|
+
@conn.exec( 'ROLLBACK' ) unless example.metadata[:without_transaction]
|
36
31
|
end
|
37
32
|
|
38
33
|
after( :all ) do
|
@@ -45,7 +40,7 @@ describe PGconn do
|
|
45
40
|
#
|
46
41
|
|
47
42
|
it "can create a connection option string from a Hash of options" do
|
48
|
-
optstring =
|
43
|
+
optstring = described_class.parse_connect_args(
|
49
44
|
:host => 'pgsql.example.com',
|
50
45
|
:dbname => 'db01',
|
51
46
|
'sslmode' => 'require'
|
@@ -58,7 +53,7 @@ describe PGconn do
|
|
58
53
|
end
|
59
54
|
|
60
55
|
it "can create a connection option string from positional parameters" do
|
61
|
-
optstring =
|
56
|
+
optstring = described_class.parse_connect_args( 'pgsql.example.com', nil, '-c geqo=off', nil,
|
62
57
|
'sales' )
|
63
58
|
|
64
59
|
optstring.should be_a( String )
|
@@ -71,7 +66,7 @@ describe PGconn do
|
|
71
66
|
end
|
72
67
|
|
73
68
|
it "can create a connection option string from a mix of positional and hash parameters" do
|
74
|
-
optstring =
|
69
|
+
optstring = described_class.parse_connect_args( 'pgsql.example.com',
|
75
70
|
:dbname => 'licensing', :user => 'jrandom' )
|
76
71
|
|
77
72
|
optstring.should be_a( String )
|
@@ -81,64 +76,94 @@ describe PGconn do
|
|
81
76
|
end
|
82
77
|
|
83
78
|
it "escapes single quotes and backslashes in connection parameters" do
|
84
|
-
|
79
|
+
described_class.parse_connect_args( "DB 'browser' \\" ).should == "host='DB \\'browser\\' \\\\'"
|
85
80
|
|
86
81
|
end
|
87
82
|
|
88
83
|
it "connects with defaults if no connection parameters are given" do
|
89
|
-
|
84
|
+
described_class.parse_connect_args.should == ''
|
90
85
|
end
|
91
86
|
|
92
87
|
it "connects successfully with connection string" do
|
93
|
-
tmpconn =
|
94
|
-
tmpconn.status.should==
|
88
|
+
tmpconn = described_class.connect(@conninfo)
|
89
|
+
tmpconn.status.should== PG::CONNECTION_OK
|
95
90
|
tmpconn.finish
|
96
91
|
end
|
97
92
|
|
98
93
|
it "connects using 7 arguments converted to strings" do
|
99
|
-
tmpconn =
|
100
|
-
tmpconn.status.should==
|
94
|
+
tmpconn = described_class.connect('localhost', @port, nil, nil, :test, nil, nil)
|
95
|
+
tmpconn.status.should== PG::CONNECTION_OK
|
101
96
|
tmpconn.finish
|
102
97
|
end
|
103
98
|
|
104
99
|
it "connects using a hash of connection parameters" do
|
105
|
-
tmpconn =
|
100
|
+
tmpconn = described_class.connect(
|
106
101
|
:host => 'localhost',
|
107
102
|
:port => @port,
|
108
103
|
:dbname => :test)
|
109
|
-
tmpconn.status.should==
|
104
|
+
tmpconn.status.should== PG::CONNECTION_OK
|
110
105
|
tmpconn.finish
|
111
106
|
end
|
112
107
|
|
113
108
|
it "raises an exception when connecting with an invalid number of arguments" do
|
114
109
|
expect {
|
115
|
-
|
110
|
+
described_class.connect( 1, 2, 3, 4, 5, 6, 7, 'extra' )
|
116
111
|
}.to raise_error( ArgumentError, /extra positional parameter/i )
|
117
112
|
end
|
118
113
|
|
119
114
|
|
120
115
|
it "can connect asynchronously" do
|
121
|
-
tmpconn =
|
122
|
-
|
116
|
+
tmpconn = described_class.connect_start( @conninfo )
|
117
|
+
tmpconn.should be_a( described_class )
|
118
|
+
socket = IO.for_fd( tmpconn.socket )
|
123
119
|
status = tmpconn.connect_poll
|
124
|
-
|
125
|
-
|
126
|
-
|
120
|
+
|
121
|
+
while status != PG::PGRES_POLLING_OK
|
122
|
+
if status == PG::PGRES_POLLING_READING
|
123
|
+
select( [socket], [], [], 5.0 ) or
|
127
124
|
raise "Asynchronous connection timed out!"
|
128
|
-
|
129
|
-
elsif
|
130
|
-
|
125
|
+
|
126
|
+
elsif status == PG::PGRES_POLLING_WRITING
|
127
|
+
select( [], [socket], [], 5.0 ) or
|
131
128
|
raise "Asynchronous connection timed out!"
|
132
|
-
end
|
133
129
|
end
|
134
130
|
status = tmpconn.connect_poll
|
135
131
|
end
|
136
|
-
|
132
|
+
|
133
|
+
tmpconn.status.should == PG::CONNECTION_OK
|
137
134
|
tmpconn.finish
|
138
135
|
end
|
139
136
|
|
137
|
+
it "can connect asynchronously for the duration of a block" do
|
138
|
+
conn = nil
|
139
|
+
|
140
|
+
described_class.connect_start(@conninfo) do |tmpconn|
|
141
|
+
tmpconn.should be_a( described_class )
|
142
|
+
conn = tmpconn
|
143
|
+
socket = IO.for_fd(tmpconn.socket)
|
144
|
+
status = tmpconn.connect_poll
|
145
|
+
|
146
|
+
while status != PG::PGRES_POLLING_OK
|
147
|
+
if status == PG::PGRES_POLLING_READING
|
148
|
+
if(not select([socket],[],[],5.0))
|
149
|
+
raise "Asynchronous connection timed out!"
|
150
|
+
end
|
151
|
+
elsif(status == PG::PGRES_POLLING_WRITING)
|
152
|
+
if(not select([],[socket],[],5.0))
|
153
|
+
raise "Asynchronous connection timed out!"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
status = tmpconn.connect_poll
|
157
|
+
end
|
158
|
+
|
159
|
+
tmpconn.status.should == PG::CONNECTION_OK
|
160
|
+
end
|
161
|
+
|
162
|
+
conn.should be_finished()
|
163
|
+
end
|
164
|
+
|
140
165
|
it "doesn't leave stale server connections after finish" do
|
141
|
-
|
166
|
+
described_class.connect(@conninfo).finish
|
142
167
|
sleep 0.5
|
143
168
|
res = @conn.exec(%[SELECT COUNT(*) AS n FROM pg_stat_activity
|
144
169
|
WHERE usename IS NOT NULL])
|
@@ -213,13 +238,13 @@ describe PGconn do
|
|
213
238
|
@conn.send_query("SELECT pg_sleep(1000)")
|
214
239
|
@conn.cancel
|
215
240
|
tmpres = @conn.get_result
|
216
|
-
if(tmpres.result_status !=
|
241
|
+
if(tmpres.result_status != PG::PGRES_TUPLES_OK)
|
217
242
|
error = true
|
218
243
|
end
|
219
244
|
error.should == true
|
220
245
|
end
|
221
246
|
|
222
|
-
it "automatically rolls back a transaction started with
|
247
|
+
it "automatically rolls back a transaction started with described_class#transaction if an exception " +
|
223
248
|
"is raised" do
|
224
249
|
# abort the per-example transaction so we can test our own
|
225
250
|
@conn.exec( 'ROLLBACK' )
|
@@ -241,10 +266,10 @@ describe PGconn do
|
|
241
266
|
it "not read past the end of a large object" do
|
242
267
|
@conn.transaction do
|
243
268
|
oid = @conn.lo_create( 0 )
|
244
|
-
fd = @conn.lo_open( oid,
|
269
|
+
fd = @conn.lo_open( oid, PG::INV_READ|PG::INV_WRITE )
|
245
270
|
@conn.lo_write( fd, "foobar" )
|
246
271
|
@conn.lo_read( fd, 10 ).should be_nil()
|
247
|
-
@conn.lo_lseek( fd, 0,
|
272
|
+
@conn.lo_lseek( fd, 0, PG::SEEK_SET )
|
248
273
|
@conn.lo_read( fd, 10 ).should == 'foobar'
|
249
274
|
end
|
250
275
|
end
|
@@ -256,7 +281,7 @@ describe PGconn do
|
|
256
281
|
|
257
282
|
pid = fork do
|
258
283
|
begin
|
259
|
-
conn =
|
284
|
+
conn = described_class.connect( @conninfo )
|
260
285
|
sleep 1
|
261
286
|
conn.exec( 'NOTIFY woo' )
|
262
287
|
ensure
|
@@ -277,7 +302,7 @@ describe PGconn do
|
|
277
302
|
|
278
303
|
pid = fork do
|
279
304
|
begin
|
280
|
-
conn =
|
305
|
+
conn = described_class.connect( @conninfo )
|
281
306
|
sleep 1
|
282
307
|
conn.exec( 'NOTIFY woo' )
|
283
308
|
ensure
|
@@ -304,7 +329,7 @@ describe PGconn do
|
|
304
329
|
|
305
330
|
pid = fork do
|
306
331
|
begin
|
307
|
-
conn =
|
332
|
+
conn = described_class.connect( @conninfo )
|
308
333
|
conn.exec( 'NOTIFY woo' )
|
309
334
|
conn.exec( 'NOTIFY war' )
|
310
335
|
conn.exec( 'NOTIFY woz' )
|
@@ -336,7 +361,7 @@ describe PGconn do
|
|
336
361
|
|
337
362
|
pid = fork do
|
338
363
|
begin
|
339
|
-
conn =
|
364
|
+
conn = described_class.connect( @conninfo )
|
340
365
|
conn.exec( 'NOTIFY woo' )
|
341
366
|
ensure
|
342
367
|
conn.finish
|
@@ -367,7 +392,7 @@ describe PGconn do
|
|
367
392
|
@conn.exec( 'LISTEN knees' )
|
368
393
|
|
369
394
|
pid = fork do
|
370
|
-
conn =
|
395
|
+
conn = described_class.connect( @conninfo )
|
371
396
|
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
372
397
|
conn.finish
|
373
398
|
exit!
|
@@ -391,7 +416,7 @@ describe PGconn do
|
|
391
416
|
@conn.exec( 'LISTEN knees' )
|
392
417
|
|
393
418
|
pid = fork do
|
394
|
-
conn =
|
419
|
+
conn = described_class.connect( @conninfo )
|
395
420
|
conn.exec( %Q{NOTIFY knees} )
|
396
421
|
conn.finish
|
397
422
|
exit!
|
@@ -414,7 +439,7 @@ describe PGconn do
|
|
414
439
|
@conn.exec( 'LISTEN knees' )
|
415
440
|
|
416
441
|
pid = fork do
|
417
|
-
conn =
|
442
|
+
conn = described_class.connect( @conninfo )
|
418
443
|
conn.exec( %Q{NOTIFY knees} )
|
419
444
|
conn.finish
|
420
445
|
exit!
|
@@ -438,7 +463,7 @@ describe PGconn do
|
|
438
463
|
@conn.exec( 'LISTEN knees' )
|
439
464
|
|
440
465
|
pid = fork do
|
441
|
-
conn =
|
466
|
+
conn = described_class.connect( @conninfo )
|
442
467
|
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
443
468
|
conn.finish
|
444
469
|
exit!
|
@@ -464,7 +489,7 @@ describe PGconn do
|
|
464
489
|
@conn.exec( 'LISTEN knees' )
|
465
490
|
|
466
491
|
pid = fork do
|
467
|
-
conn =
|
492
|
+
conn = described_class.connect( @conninfo )
|
468
493
|
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
469
494
|
conn.finish
|
470
495
|
exit!
|
@@ -488,7 +513,7 @@ describe PGconn do
|
|
488
513
|
@conn.exec( 'LISTEN knees' )
|
489
514
|
|
490
515
|
pid = fork do
|
491
|
-
conn =
|
516
|
+
conn = described_class.connect( @conninfo )
|
492
517
|
conn.exec( %Q{NOTIFY knees, 'skirt and boots'} )
|
493
518
|
conn.finish
|
494
519
|
exit!
|
@@ -512,7 +537,7 @@ describe PGconn do
|
|
512
537
|
it "yields the result if block is given to exec" do
|
513
538
|
rval = @conn.exec( "select 1234::int as a union select 5678::int as a" ) do |result|
|
514
539
|
values = []
|
515
|
-
result.should be_kind_of(
|
540
|
+
result.should be_kind_of( PG::Result )
|
516
541
|
result.ntuples.should == 2
|
517
542
|
result.each do |tuple|
|
518
543
|
values << tuple['a']
|
@@ -543,7 +568,7 @@ describe PGconn do
|
|
543
568
|
end
|
544
569
|
|
545
570
|
|
546
|
-
it "
|
571
|
+
it "described_class#block shouldn't block a second thread" do
|
547
572
|
t = Thread.new do
|
548
573
|
@conn.send_query( "select pg_sleep(3)" )
|
549
574
|
@conn.block
|
@@ -556,7 +581,7 @@ describe PGconn do
|
|
556
581
|
t.join
|
557
582
|
end
|
558
583
|
|
559
|
-
it "
|
584
|
+
it "described_class#block should allow a timeout" do
|
560
585
|
@conn.send_query( "select pg_sleep(3)" )
|
561
586
|
|
562
587
|
start = Time.now
|
@@ -568,7 +593,7 @@ describe PGconn do
|
|
568
593
|
|
569
594
|
|
570
595
|
it "can encrypt a string given a password and username" do
|
571
|
-
|
596
|
+
described_class.encrypt_password("postgres", "postgres").
|
572
597
|
should =~ /\S+/
|
573
598
|
end
|
574
599
|
|
@@ -576,13 +601,13 @@ describe PGconn do
|
|
576
601
|
it "raises an appropriate error if either of the required arguments for encrypt_password " +
|
577
602
|
"is not valid" do
|
578
603
|
expect {
|
579
|
-
|
604
|
+
described_class.encrypt_password( nil, nil )
|
580
605
|
}.to raise_error( TypeError )
|
581
606
|
expect {
|
582
|
-
|
607
|
+
described_class.encrypt_password( "postgres", nil )
|
583
608
|
}.to raise_error( TypeError )
|
584
609
|
expect {
|
585
|
-
|
610
|
+
described_class.encrypt_password( nil, "postgres" )
|
586
611
|
}.to raise_error( TypeError )
|
587
612
|
end
|
588
613
|
|
@@ -627,14 +652,14 @@ describe PGconn do
|
|
627
652
|
|
628
653
|
it "can connect asynchronously" do
|
629
654
|
serv = TCPServer.new( '127.0.0.1', 54320 )
|
630
|
-
conn =
|
631
|
-
conn.connect_poll.should ==
|
655
|
+
conn = described_class.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
|
656
|
+
conn.connect_poll.should == PG::PGRES_POLLING_WRITING
|
632
657
|
select( nil, [IO.for_fd(conn.socket)], nil, 0.2 )
|
633
658
|
serv.close
|
634
|
-
if conn.connect_poll ==
|
659
|
+
if conn.connect_poll == PG::PGRES_POLLING_READING
|
635
660
|
select( [IO.for_fd(conn.socket)], nil, nil, 0.2 )
|
636
661
|
end
|
637
|
-
conn.connect_poll.should ==
|
662
|
+
conn.connect_poll.should == PG::PGRES_POLLING_FAILED
|
638
663
|
end
|
639
664
|
|
640
665
|
it "discards previous results (if any) before waiting on an #async_exec"
|
@@ -647,4 +672,146 @@ describe PGconn do
|
|
647
672
|
result.should == { 'one' => '47' }
|
648
673
|
end
|
649
674
|
|
675
|
+
|
676
|
+
describe "multinationalization support", :ruby_19 => true do
|
677
|
+
|
678
|
+
it "should return the same bytes in text format that are sent as inline text" do
|
679
|
+
binary_file = File.join(Dir.pwd, 'spec/data', 'random_binary_data')
|
680
|
+
in_bytes = File.open(binary_file, 'r:ASCII-8BIT').read
|
681
|
+
escaped_bytes = described_class.escape_bytea( in_bytes )
|
682
|
+
out_bytes = nil
|
683
|
+
|
684
|
+
@conn.transaction do |conn|
|
685
|
+
conn.exec("SET standard_conforming_strings=on")
|
686
|
+
res = conn.exec("VALUES ('#{escaped_bytes}'::bytea)", [], 0)
|
687
|
+
out_bytes = described_class.unescape_bytea( res[0]['column1'] )
|
688
|
+
end
|
689
|
+
|
690
|
+
out_bytes.should == in_bytes
|
691
|
+
end
|
692
|
+
|
693
|
+
describe "rubyforge #22925: m17n support" do
|
694
|
+
it "should return results in the same encoding as the client (iso-8859-1)" do
|
695
|
+
out_string = nil
|
696
|
+
@conn.transaction do |conn|
|
697
|
+
conn.internal_encoding = 'iso8859-1'
|
698
|
+
res = conn.exec("VALUES ('fantasia')", [], 0)
|
699
|
+
out_string = res[0]['column1']
|
700
|
+
end
|
701
|
+
out_string.should == 'fantasia'
|
702
|
+
out_string.encoding.should == Encoding::ISO8859_1
|
703
|
+
end
|
704
|
+
|
705
|
+
it "should return results in the same encoding as the client (utf-8)" do
|
706
|
+
out_string = nil
|
707
|
+
@conn.transaction do |conn|
|
708
|
+
conn.internal_encoding = 'utf-8'
|
709
|
+
res = conn.exec("VALUES ('世界線航跡蔵')", [], 0)
|
710
|
+
out_string = res[0]['column1']
|
711
|
+
end
|
712
|
+
out_string.should == '世界線航跡蔵'
|
713
|
+
out_string.encoding.should == Encoding::UTF_8
|
714
|
+
end
|
715
|
+
|
716
|
+
it "should return results in the same encoding as the client (EUC-JP)" do
|
717
|
+
out_string = nil
|
718
|
+
@conn.transaction do |conn|
|
719
|
+
conn.internal_encoding = 'EUC-JP'
|
720
|
+
stmt = "VALUES ('世界線航跡蔵')".encode('EUC-JP')
|
721
|
+
res = conn.exec(stmt, [], 0)
|
722
|
+
out_string = res[0]['column1']
|
723
|
+
end
|
724
|
+
out_string.should == '世界線航跡蔵'.encode('EUC-JP')
|
725
|
+
out_string.encoding.should == Encoding::EUC_JP
|
726
|
+
end
|
727
|
+
|
728
|
+
it "returns the results in the correct encoding even if the client_encoding has " +
|
729
|
+
"changed since the results were fetched" do
|
730
|
+
out_string = nil
|
731
|
+
@conn.transaction do |conn|
|
732
|
+
conn.internal_encoding = 'EUC-JP'
|
733
|
+
stmt = "VALUES ('世界線航跡蔵')".encode('EUC-JP')
|
734
|
+
res = conn.exec(stmt, [], 0)
|
735
|
+
conn.internal_encoding = 'utf-8'
|
736
|
+
out_string = res[0]['column1']
|
737
|
+
end
|
738
|
+
out_string.should == '世界線航跡蔵'.encode('EUC-JP')
|
739
|
+
out_string.encoding.should == Encoding::EUC_JP
|
740
|
+
end
|
741
|
+
|
742
|
+
it "the connection should return ASCII-8BIT when it's set to SQL_ASCII" do
|
743
|
+
@conn.exec "SET client_encoding TO SQL_ASCII"
|
744
|
+
@conn.client_encoding.should == Encoding::ASCII_8BIT
|
745
|
+
end
|
746
|
+
|
747
|
+
it "works around the unsupported JOHAB encoding by returning stuff in 'ASCII_8BIT'" do
|
748
|
+
pending "figuring out how to create a string in the JOHAB encoding" do
|
749
|
+
out_string = nil
|
750
|
+
@conn.transaction do |conn|
|
751
|
+
conn.exec( "set client_encoding = 'JOHAB';" )
|
752
|
+
stmt = "VALUES ('foo')".encode('JOHAB')
|
753
|
+
res = conn.exec( stmt, [], 0 )
|
754
|
+
out_string = res[0]['column1']
|
755
|
+
end
|
756
|
+
out_string.should == 'foo'.encode( Encoding::ASCII_8BIT )
|
757
|
+
out_string.encoding.should == Encoding::ASCII_8BIT
|
758
|
+
end
|
759
|
+
end
|
760
|
+
|
761
|
+
it "uses the client encoding for escaped string" do
|
762
|
+
original = "string to escape".force_encoding( "euc-jp" )
|
763
|
+
@conn.set_client_encoding( "euc_jp" )
|
764
|
+
escaped = @conn.escape( original )
|
765
|
+
escaped.encoding.should == Encoding::EUC_JP
|
766
|
+
end
|
767
|
+
end
|
768
|
+
|
769
|
+
|
770
|
+
describe "Ruby 1.9.x default_internal encoding" do
|
771
|
+
|
772
|
+
it "honors the Encoding.default_internal if it's set and the synchronous interface is used" do
|
773
|
+
@conn.transaction do |txn_conn|
|
774
|
+
txn_conn.internal_encoding = Encoding::ISO8859_1
|
775
|
+
txn_conn.exec( "CREATE TABLE defaultinternaltest ( foo text )" )
|
776
|
+
txn_conn.exec( "INSERT INTO defaultinternaltest VALUES ('Grün und Weiß')" )
|
777
|
+
end
|
778
|
+
|
779
|
+
begin
|
780
|
+
prev_encoding = Encoding.default_internal
|
781
|
+
Encoding.default_internal = Encoding::UTF_8
|
782
|
+
|
783
|
+
conn = PG.connect( @conninfo )
|
784
|
+
conn.internal_encoding.should == Encoding::UTF_8
|
785
|
+
res = conn.exec( "SELECT foo FROM defaultinternaltest" )
|
786
|
+
res[0]['foo'].encoding.should == Encoding::UTF_8
|
787
|
+
ensure
|
788
|
+
conn.finish if conn
|
789
|
+
Encoding.default_internal = prev_encoding
|
790
|
+
end
|
791
|
+
end
|
792
|
+
|
793
|
+
end
|
794
|
+
|
795
|
+
|
796
|
+
it "encodes exception messages with the connection's encoding (#96)", :without_transaction do
|
797
|
+
# Use a new connection so the client_encoding isn't set outside of this example
|
798
|
+
conn = PG.connect( @conninfo )
|
799
|
+
conn.client_encoding = 'iso-8859-15'
|
800
|
+
|
801
|
+
conn.transaction do
|
802
|
+
conn.exec "CREATE TABLE foo (bar TEXT)"
|
803
|
+
|
804
|
+
begin
|
805
|
+
query = "INSERT INTO foo VALUES ('Côte d'Ivoire')".encode( 'iso-8859-15' )
|
806
|
+
conn.exec( query )
|
807
|
+
rescue => err
|
808
|
+
err.message.encoding.should == Encoding::ISO8859_15
|
809
|
+
else
|
810
|
+
fail "No exception raised?!"
|
811
|
+
end
|
812
|
+
end
|
813
|
+
|
814
|
+
end
|
815
|
+
|
816
|
+
end
|
650
817
|
end
|