pg 0.12.2-x86-mingw32 → 0.13.0-x86-mingw32

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.
Files changed (50) hide show
  1. data/.hoerc +2 -0
  2. data/.tm_properties +12 -0
  3. data/ChangeLog +166 -59
  4. data/Contributors.rdoc +7 -0
  5. data/History.rdoc +29 -0
  6. data/LICENSE +12 -14
  7. data/Manifest.txt +15 -14
  8. data/{BSD → POSTGRES} +0 -0
  9. data/{README.OS_X.rdoc → README-OS_X.rdoc} +0 -0
  10. data/{README.windows.rdoc → README-Windows.rdoc} +0 -0
  11. data/README.ja.rdoc +1 -1
  12. data/README.rdoc +39 -27
  13. data/Rakefile +1 -5
  14. data/Rakefile.cross +2 -2
  15. data/ext/extconf.rb +8 -2
  16. data/ext/pg.c +232 -4297
  17. data/ext/pg.h +88 -23
  18. data/ext/pg_connection.c +3288 -0
  19. data/ext/pg_result.c +905 -0
  20. data/lib/1.8/pg_ext.so +0 -0
  21. data/lib/1.9/pg_ext.so +0 -0
  22. data/lib/pg.rb +26 -43
  23. data/lib/pg/connection.rb +58 -0
  24. data/lib/pg/constants.rb +11 -0
  25. data/lib/pg/exceptions.rb +11 -0
  26. data/lib/pg/result.rb +11 -0
  27. data/misc/openssl-pg-segfault.rb +1 -1
  28. data/sample/async_api.rb +16 -21
  29. data/sample/async_copyto.rb +1 -1
  30. data/sample/async_mixed.rb +56 -0
  31. data/sample/copyfrom.rb +1 -1
  32. data/sample/copyto.rb +1 -1
  33. data/sample/cursor.rb +1 -1
  34. data/sample/losample.rb +6 -6
  35. data/sample/notify_wait.rb +51 -22
  36. data/sample/test_binary_values.rb +4 -6
  37. data/spec/lib/helpers.rb +14 -10
  38. data/spec/{pgconn_spec.rb → pg/connection_spec.rb} +228 -60
  39. data/spec/{pgresult_spec.rb → pg/result_spec.rb} +31 -35
  40. data/spec/pg_spec.rb +22 -0
  41. metadata +52 -41
  42. data/GPL +0 -340
  43. data/ext/compat.c +0 -541
  44. data/ext/compat.h +0 -184
  45. data/sample/psql.rb +0 -1181
  46. data/sample/psqlHelp.rb +0 -158
  47. data/sample/test1.rb +0 -60
  48. data/sample/test2.rb +0 -44
  49. data/sample/test4.rb +0 -71
  50. data/spec/m17n_spec.rb +0 -170
@@ -2,18 +2,16 @@
2
2
 
3
3
  require 'pg'
4
4
 
5
- connhash = { :dbname => 'test' }
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" % [
@@ -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
- RSpec.configure do |config|
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 = PGconn.connect( @conninfo )
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
- # encoding: utf-8
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 PGconn do
23
- include PgTestingHelpers
24
-
19
+ describe PG::Connection do
25
20
 
26
21
  before( :all ) do
27
- @conn = setup_testing_db( "PGconn" )
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 = PGconn.parse_connect_args(
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 = PGconn.parse_connect_args( 'pgsql.example.com', nil, '-c geqo=off', nil,
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 = PGconn.parse_connect_args( 'pgsql.example.com',
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
- PGconn.parse_connect_args( "DB 'browser' \\" ).should == "host='DB \\'browser\\' \\\\'"
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
- PGconn.parse_connect_args.should == ''
84
+ described_class.parse_connect_args.should == ''
90
85
  end
91
86
 
92
87
  it "connects successfully with connection string" do
93
- tmpconn = PGconn.connect(@conninfo)
94
- tmpconn.status.should== PGconn::CONNECTION_OK
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 = PGconn.connect('localhost', @port, nil, nil, :test, nil, nil)
100
- tmpconn.status.should== PGconn::CONNECTION_OK
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 = PGconn.connect(
100
+ tmpconn = described_class.connect(
106
101
  :host => 'localhost',
107
102
  :port => @port,
108
103
  :dbname => :test)
109
- tmpconn.status.should== PGconn::CONNECTION_OK
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
- PGconn.connect( 1, 2, 3, 4, 5, 6, 7, 'extra' )
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 = PGconn.connect_start(@conninfo)
122
- socket = IO.for_fd(tmpconn.socket)
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
- while(status != PGconn::PGRES_POLLING_OK) do
125
- if(status == PGconn::PGRES_POLLING_READING)
126
- if(not select([socket],[],[],5.0))
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
- end
129
- elsif(status == PGconn::PGRES_POLLING_WRITING)
130
- if(not select([],[socket],[],5.0))
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
- tmpconn.status.should== PGconn::CONNECTION_OK
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
- PGconn.connect(@conninfo).finish
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 != PGresult::PGRES_TUPLES_OK)
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 PGconn#transaction if an exception " +
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, PGconn::INV_READ|PGconn::INV_WRITE )
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, PGconn::SEEK_SET )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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 = PGconn.connect( @conninfo )
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( PGresult )
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 "PGconn#block shouldn't block a second thread" do
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 "PGconn#block should allow a timeout" do
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
- PGconn.encrypt_password("postgres", "postgres").
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
- PGconn.encrypt_password( nil, nil )
604
+ described_class.encrypt_password( nil, nil )
580
605
  }.to raise_error( TypeError )
581
606
  expect {
582
- PGconn.encrypt_password( "postgres", nil )
607
+ described_class.encrypt_password( "postgres", nil )
583
608
  }.to raise_error( TypeError )
584
609
  expect {
585
- PGconn.encrypt_password( nil, "postgres" )
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 = PGconn.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
631
- conn.connect_poll.should == PGconn::PGRES_POLLING_WRITING
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 == PGconn::PGRES_POLLING_READING
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 == PGconn::PGRES_POLLING_FAILED
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,147 @@ 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.internal_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
+ conn.finish if conn
815
+ end
816
+
817
+ end
650
818
  end