pg 0.18.0 → 1.0.0

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 (66) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/BSDL +2 -2
  4. data/ChangeLog +1221 -4
  5. data/History.rdoc +130 -0
  6. data/Manifest.txt +0 -18
  7. data/README-Windows.rdoc +15 -26
  8. data/README.rdoc +16 -10
  9. data/Rakefile +32 -23
  10. data/Rakefile.cross +56 -38
  11. data/ext/errorcodes.def +33 -0
  12. data/ext/errorcodes.txt +15 -1
  13. data/ext/extconf.rb +27 -35
  14. data/ext/gvl_wrappers.c +4 -0
  15. data/ext/gvl_wrappers.h +27 -39
  16. data/ext/pg.c +19 -51
  17. data/ext/pg.h +22 -79
  18. data/ext/pg_binary_decoder.c +3 -1
  19. data/ext/pg_binary_encoder.c +14 -12
  20. data/ext/pg_coder.c +31 -10
  21. data/ext/pg_connection.c +350 -263
  22. data/ext/pg_copy_coder.c +34 -4
  23. data/ext/pg_result.c +27 -25
  24. data/ext/pg_text_decoder.c +9 -10
  25. data/ext/pg_text_encoder.c +93 -73
  26. data/ext/pg_type_map.c +20 -13
  27. data/ext/pg_type_map_by_column.c +7 -7
  28. data/ext/pg_type_map_by_mri_type.c +2 -2
  29. data/ext/pg_type_map_in_ruby.c +4 -7
  30. data/ext/util.c +3 -3
  31. data/ext/util.h +1 -1
  32. data/lib/pg/basic_type_mapping.rb +69 -42
  33. data/lib/pg/connection.rb +89 -38
  34. data/lib/pg/result.rb +10 -5
  35. data/lib/pg/text_decoder.rb +12 -3
  36. data/lib/pg/text_encoder.rb +8 -0
  37. data/lib/pg.rb +18 -10
  38. data/spec/helpers.rb +9 -16
  39. data/spec/pg/basic_type_mapping_spec.rb +58 -4
  40. data/spec/pg/connection_spec.rb +477 -217
  41. data/spec/pg/result_spec.rb +14 -7
  42. data/spec/pg/type_map_by_class_spec.rb +2 -2
  43. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  44. data/spec/pg/type_spec.rb +145 -33
  45. data/spec/pg_spec.rb +1 -1
  46. data.tar.gz.sig +0 -0
  47. metadata +67 -66
  48. metadata.gz.sig +0 -0
  49. data/sample/array_insert.rb +0 -20
  50. data/sample/async_api.rb +0 -106
  51. data/sample/async_copyto.rb +0 -39
  52. data/sample/async_mixed.rb +0 -56
  53. data/sample/check_conn.rb +0 -21
  54. data/sample/copyfrom.rb +0 -81
  55. data/sample/copyto.rb +0 -19
  56. data/sample/cursor.rb +0 -21
  57. data/sample/disk_usage_report.rb +0 -186
  58. data/sample/issue-119.rb +0 -94
  59. data/sample/losample.rb +0 -69
  60. data/sample/minimal-testcase.rb +0 -17
  61. data/sample/notify_wait.rb +0 -72
  62. data/sample/pg_statistics.rb +0 -294
  63. data/sample/replication_monitor.rb +0 -231
  64. data/sample/test_binary_values.rb +0 -33
  65. data/sample/wal_shipper.rb +0 -434
  66. data/sample/warehouse_partitions.rb +0 -320
@@ -39,7 +39,7 @@ describe PG::Result do
39
39
  expect( e.to_a ).to eq [{'a'=>'1', 'b'=>'2'}]
40
40
  end
41
41
 
42
- context "result streaming", :postgresql_92 do
42
+ context "result streaming" do
43
43
  it "can iterate over all tuples in single row mode" do
44
44
  @conn.send_query( "SELECT generate_series(2,4) AS a; SELECT 1 AS b, generate_series(5,6) AS c" )
45
45
  @conn.set_single_row_mode
@@ -100,11 +100,11 @@ describe PG::Result do
100
100
  expect( res[0]['n'] ).to be_nil()
101
101
  end
102
102
 
103
- it "encapsulates errors in a PGError object" do
103
+ it "encapsulates errors in a PG::Error object" do
104
104
  exception = nil
105
105
  begin
106
106
  @conn.exec( "SELECT * FROM nonexistant_table" )
107
- rescue PGError => err
107
+ rescue PG::Error => err
108
108
  exception = err
109
109
  end
110
110
 
@@ -136,7 +136,7 @@ describe PG::Result do
136
136
  exception = nil
137
137
  begin
138
138
  @conn.exec( "INSERT INTO integrity VALUES (NULL)" )
139
- rescue PGError => err
139
+ rescue PG::Error => err
140
140
  exception = err
141
141
  end
142
142
  result = exception.result
@@ -152,7 +152,7 @@ describe PG::Result do
152
152
  sqlstate = nil
153
153
  begin
154
154
  res = @conn.exec("SELECT 1/0")
155
- rescue PGError => e
155
+ rescue PG::Error => e
156
156
  sqlstate = e.result.result_error_field( PG::PG_DIAG_SQLSTATE ).to_i
157
157
  end
158
158
  expect( sqlstate ).to eq( 22012 )
@@ -199,7 +199,7 @@ describe PG::Result do
199
199
  expect( out_bytes ).to eq( in_bytes )
200
200
  end
201
201
 
202
- it "returns the parameter type of the specified prepared statement parameter", :postgresql_92 do
202
+ it "returns the parameter type of the specified prepared statement parameter" do
203
203
  query = 'SELECT * FROM pg_stat_activity WHERE user = $1::name AND query = $2::text'
204
204
  @conn.prepare( 'queryfinder', query )
205
205
  res = @conn.describe_prepared( 'queryfinder' )
@@ -386,7 +386,7 @@ describe PG::Result do
386
386
  end
387
387
 
388
388
  it "the raised result is nil in case of a connection error" do
389
- c = PGconn.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
389
+ c = PG::Connection.connect_start( '127.0.0.1', 54320, "", "", "me", "xxxx", "somedb" )
390
390
  expect {
391
391
  c.exec "select 1"
392
392
  }.to raise_error {|error|
@@ -403,6 +403,13 @@ describe PG::Result do
403
403
  expect( r.cleared? ).to eq(true)
404
404
  end
405
405
 
406
+ it "can be inspected before and after clear" do
407
+ r = @conn.exec "select 1"
408
+ expect( r.inspect ).to match(/status=PGRES_TUPLES_OK/)
409
+ r.clear
410
+ expect( r.inspect ).to match(/cleared/)
411
+ end
412
+
406
413
  context 'result value conversions with TypeMapByColumn' do
407
414
  let!(:textdec_int){ PG::TextDecoder::Integer.new name: 'INT4', oid: 23 }
408
415
  let!(:textdec_float){ PG::TextDecoder::Float.new name: 'FLOAT4', oid: 700 }
@@ -59,7 +59,7 @@ describe PG::TypeMapByClass do
59
59
  it "should retrieve particular conversions" do
60
60
  expect( tm[Integer] ).to eq(binaryenc_int)
61
61
  expect( tm[Float] ).to eq(textenc_float)
62
- expect( tm[Bignum] ).to be_nil
62
+ expect( tm[Range] ).to be_nil
63
63
  expect( derived_tm[raise_class] ).to be_kind_of(Proc)
64
64
  expect( derived_tm[Array] ).to eq(:array_type_map_for)
65
65
  end
@@ -102,7 +102,7 @@ describe PG::TypeMapByClass do
102
102
 
103
103
  it "should allow mixed type conversions" do
104
104
  res = @conn.exec_params( "SELECT $1, $2, $3", [5, 1.23, :TestSymbol], 0, tm )
105
- expect( res.values ).to eq([['5', '1.23', '[:TestSymbol]']])
105
+ expect( res.values ).to eq([['5', '1.23', "[:TestSymbol, #{@conn.internal_encoding.inspect}]"]])
106
106
  expect( res.ftype(0) ).to eq(20)
107
107
  end
108
108
 
@@ -116,7 +116,7 @@ describe PG::TypeMapByMriType do
116
116
 
117
117
  it "should allow mixed type conversions" do
118
118
  res = @conn.exec_params( "SELECT $1, $2, $3", [5, 1.23, :TestSymbol], 0, tm )
119
- expect( res.values ).to eq([['5', '1.23', '[:TestSymbol]']])
119
+ expect( res.values ).to eq([['5', '1.23', "[:TestSymbol, #{@conn.internal_encoding.inspect}]"]])
120
120
  expect( res.ftype(0) ).to eq(20)
121
121
  end
122
122
 
data/spec/pg/type_spec.rb CHANGED
@@ -15,6 +15,8 @@ describe "PG::Type derivations" do
15
15
  let!(:textdec_string) { PG::TextDecoder::String.new }
16
16
  let!(:textenc_timestamp) { PG::TextEncoder::TimestampWithoutTimeZone.new }
17
17
  let!(:textdec_timestamp) { PG::TextDecoder::TimestampWithoutTimeZone.new }
18
+ let!(:textenc_timestamptz) { PG::TextEncoder::TimestampWithTimeZone.new }
19
+ let!(:textdec_timestamptz) { PG::TextDecoder::TimestampWithTimeZone.new }
18
20
  let!(:textenc_bytea) { PG::TextEncoder::Bytea.new }
19
21
  let!(:textdec_bytea) { PG::TextDecoder::Bytea.new }
20
22
  let!(:binaryenc_int2) { PG::BinaryEncoder::Int2.new }
@@ -37,6 +39,14 @@ describe "PG::Type derivations" do
37
39
  end.new
38
40
  end
39
41
 
42
+ let!(:intenc_incrementer_with_encoding) do
43
+ Class.new(PG::SimpleEncoder) do
44
+ def encode(value, encoding)
45
+ r = (value.to_i + 1).to_s + " #{encoding}"
46
+ r.encode!(encoding)
47
+ end
48
+ end.new
49
+ end
40
50
  let!(:intenc_incrementer_with_int_result) do
41
51
  Class.new(PG::SimpleEncoder) do
42
52
  def encode(value)
@@ -65,7 +75,7 @@ describe "PG::Type derivations" do
65
75
  expect( intdec_incrementer.decode("3") ).to eq( 4 )
66
76
  end
67
77
 
68
- it "should decode integers of different lengths form text format" do
78
+ it "should decode integers of different lengths from text format" do
69
79
  30.times do |zeros|
70
80
  expect( textdec_int.decode("1" + "0"*zeros) ).to eq( 10 ** zeros )
71
81
  expect( textdec_int.decode(zeros==0 ? "0" : "9"*zeros) ).to eq( 10 ** zeros - 1 )
@@ -85,6 +95,55 @@ describe "PG::Type derivations" do
85
95
  expect( textdec_bytea.decode("\\377\\000") ).to eq( "\xff\0".b )
86
96
  end
87
97
 
98
+ context 'timestamps' do
99
+ it 'decodes timestamps without timezone' do
100
+ expect( textdec_timestamp.decode('2016-01-02 23:23:59.123456') ).
101
+ to be_within(0.000001).of( Time.new(2016,01,02, 23, 23, 59.123456) )
102
+ end
103
+ it 'decodes timestamps with hour timezone' do
104
+ expect( textdec_timestamptz.decode('2015-01-26 17:26:42.691511-04') ).
105
+ to be_within(0.000001).of( Time.new(2015,01,26, 17, 26, 42.691511, "-04:00") )
106
+ expect( textdec_timestamptz.decode('2015-01-26 17:26:42.691511+10') ).
107
+ to be_within(0.000001).of( Time.new(2015,01,26, 17, 26, 42.691511, "+10:00") )
108
+ end
109
+ it 'decodes timestamps with hour:minute timezone' do
110
+ expect( textdec_timestamptz.decode('2015-01-26 17:26:42.691511-04:15') ).
111
+ to be_within(0.000001).of( Time.new(2015,01,26, 17, 26, 42.691511, "-04:15") )
112
+ expect( textdec_timestamptz.decode('2015-01-26 17:26:42.691511-0430') ).
113
+ to be_within(0.000001).of( Time.new(2015,01,26, 17, 26, 42.691511, "-04:30") )
114
+ expect( textdec_timestamptz.decode('2015-01-26 17:26:42.691511+10:45') ).
115
+ to be_within(0.000001).of( Time.new(2015,01,26, 17, 26, 42.691511, "+10:45") )
116
+ end
117
+ it 'decodes timestamps with hour:minute:sec timezone' do
118
+ # SET TIME ZONE 'Europe/Dublin'; -- Was UTC−00:25:21 until 1916
119
+ # SELECT '1900-01-01'::timestamptz;
120
+ # -- "1900-01-01 00:00:00-00:25:21"
121
+ expect( textdec_timestamptz.decode('1916-01-01 00:00:00-00:25:21') ).
122
+ to be_within(0.000001).of( Time.new(1916, 1, 1, 0, 0, 0, "-00:25:21") )
123
+ end
124
+ end
125
+
126
+ context 'identifier quotation' do
127
+ it 'should build an array out of an quoted identifier string' do
128
+ quoted_type = PG::TextDecoder::Identifier.new
129
+ expect( quoted_type.decode(%["A.".".B"]) ).to eq( ["A.", ".B"] )
130
+ expect( quoted_type.decode(%["'A"".""B'"]) ).to eq( ['\'A"."B\''] )
131
+ end
132
+
133
+ it 'should split unquoted identifier string' do
134
+ quoted_type = PG::TextDecoder::Identifier.new
135
+ expect( quoted_type.decode(%[a.b]) ).to eq( ['a','b'] )
136
+ expect( quoted_type.decode(%[a]) ).to eq( ['a'] )
137
+ end
138
+
139
+ it 'should split identifier string with correct character encoding' do
140
+ quoted_type = PG::TextDecoder::Identifier.new
141
+ v = quoted_type.decode(%[Héllo].encode("iso-8859-1")).first
142
+ expect( v.encoding ).to eq( Encoding::ISO_8859_1 )
143
+ expect( v ).to eq( %[Héllo].encode(Encoding::ISO_8859_1) )
144
+ end
145
+ end
146
+
88
147
  it "should raise when decode method is called with wrong args" do
89
148
  expect{ textdec_int.decode() }.to raise_error(ArgumentError)
90
149
  expect{ textdec_int.decode("123", 2, 3, 4) }.to raise_error(ArgumentError)
@@ -156,10 +215,39 @@ describe "PG::Type derivations" do
156
215
  expect( textenc_bytea.encode("\x00\x01\x02\x03\xef".b) ).to eq( "\\x00010203ef" )
157
216
  end
158
217
 
218
+ context 'identifier quotation' do
219
+ it 'should quote and escape identifier' do
220
+ quoted_type = PG::TextEncoder::Identifier.new
221
+ expect( quoted_type.encode(['schema','table','col']) ).to eq( %["schema"."table"."col"] )
222
+ expect( quoted_type.encode(['A.','.B']) ).to eq( %["A.".".B"] )
223
+ expect( quoted_type.encode(%['A"."B']) ).to eq( %["'A"".""B'"] )
224
+ expect( quoted_type.encode( nil ) ).to be_nil
225
+ end
226
+
227
+ it 'should quote identifiers with correct character encoding' do
228
+ quoted_type = PG::TextEncoder::Identifier.new
229
+ v = quoted_type.encode(['Héllo'], "iso-8859-1")
230
+ expect( v ).to eq( %["Héllo"].encode(Encoding::ISO_8859_1) )
231
+ expect( v.encoding ).to eq( Encoding::ISO_8859_1 )
232
+ end
233
+
234
+ it "will raise a TypeError for invalid arguments to quote_ident" do
235
+ quoted_type = PG::TextEncoder::Identifier.new
236
+ expect{ quoted_type.encode( [nil] ) }.to raise_error(TypeError)
237
+ expect{ quoted_type.encode( [['a']] ) }.to raise_error(TypeError)
238
+ end
239
+ end
240
+
159
241
  it "should encode with ruby encoder" do
160
242
  expect( intenc_incrementer.encode(3) ).to eq( "4 " )
161
243
  end
162
244
 
245
+ it "should encode with ruby encoder and given character encoding" do
246
+ r = intenc_incrementer_with_encoding.encode(3, Encoding::CP850)
247
+ expect( r ).to eq( "4 CP850" )
248
+ expect( r.encoding ).to eq( Encoding::CP850 )
249
+ end
250
+
163
251
  it "should return when ruby encoder returns non string values" do
164
252
  expect( intenc_incrementer_with_int_result.encode(3) ).to eq( 4 )
165
253
  end
@@ -347,20 +435,6 @@ describe "PG::Type derivations" do
347
435
  array_type = PG::TextDecoder::Array.new elements_type: nil
348
436
  expect( array_type.decode(%[{3,4}]) ).to eq( ['3','4'] )
349
437
  end
350
-
351
- context 'identifier quotation' do
352
- it 'should build an array out of an quoted identifier string' do
353
- quoted_type = PG::TextDecoder::Identifier.new elements_type: textdec_string
354
- expect( quoted_type.decode(%["A.".".B"]) ).to eq( ["A.", ".B"] )
355
- expect( quoted_type.decode(%["'A"".""B'"]) ).to eq( ['\'A"."B\''] )
356
- end
357
-
358
- it 'should split unquoted identifier string' do
359
- quoted_type = PG::TextDecoder::Identifier.new elements_type: textdec_string
360
- expect( quoted_type.decode(%[a.b]) ).to eq( ['a','b'] )
361
- expect( quoted_type.decode(%[a]) ).to eq( ['a'] )
362
- end
363
- end
364
438
  end
365
439
 
366
440
  describe '#encode' do
@@ -401,9 +475,18 @@ describe "PG::Type derivations" do
401
475
  end
402
476
 
403
477
  context 'array of types with encoder in ruby space' do
404
- it 'encodes with quotation' do
478
+ it 'encodes with quotation and default character encoding' do
479
+ array_type = PG::TextEncoder::Array.new elements_type: intenc_incrementer, needs_quotation: true
480
+ r = array_type.encode([3,4])
481
+ expect( r ).to eq( %[{"4 ","5 "}] )
482
+ expect( r.encoding ).to eq( Encoding::ASCII_8BIT )
483
+ end
484
+
485
+ it 'encodes with quotation and given character encoding' do
405
486
  array_type = PG::TextEncoder::Array.new elements_type: intenc_incrementer, needs_quotation: true
406
- expect( array_type.encode([3,4]) ).to eq( %[{"4 ","5 "}] )
487
+ r = array_type.encode([3,4], Encoding::CP850)
488
+ expect( r ).to eq( %[{"4 ","5 "}] )
489
+ expect( r.encoding ).to eq( Encoding::CP850 )
407
490
  end
408
491
 
409
492
  it 'encodes without quotation' do
@@ -411,6 +494,20 @@ describe "PG::Type derivations" do
411
494
  expect( array_type.encode([3,4]) ).to eq( %[{4 ,5 }] )
412
495
  end
413
496
 
497
+ it 'encodes with default character encoding' do
498
+ array_type = PG::TextEncoder::Array.new elements_type: intenc_incrementer_with_encoding
499
+ r = array_type.encode([3,4])
500
+ expect( r ).to eq( %[{"4 ASCII-8BIT","5 ASCII-8BIT"}] )
501
+ expect( r.encoding ).to eq( Encoding::ASCII_8BIT )
502
+ end
503
+
504
+ it 'encodes with given character encoding' do
505
+ array_type = PG::TextEncoder::Array.new elements_type: intenc_incrementer_with_encoding
506
+ r = array_type.encode([3,4], Encoding::CP850)
507
+ expect( r ).to eq( %[{"4 CP850","5 CP850"}] )
508
+ expect( r.encoding ).to eq( Encoding::CP850 )
509
+ end
510
+
414
511
  it "should raise when ruby encoder returns non string values" do
415
512
  array_type = PG::TextEncoder::Array.new elements_type: intenc_incrementer_with_int_result, needs_quotation: false
416
513
  expect{ array_type.encode([3,4]) }.to raise_error(TypeError)
@@ -422,27 +519,18 @@ describe "PG::Type derivations" do
422
519
  expect( textenc_float_array.encode(1234) ).to eq( "1234" )
423
520
  end
424
521
 
425
- context 'identifier quotation' do
426
- it 'should quote and escape identifier' do
427
- quoted_type = PG::TextEncoder::Identifier.new elements_type: textenc_string
428
- expect( quoted_type.encode(['schema','table','col']) ).to eq( %["schema"."table"."col"] )
429
- expect( quoted_type.encode(['A.','.B']) ).to eq( %["A.".".B"] )
430
- expect( quoted_type.encode(%['A"."B']) ).to eq( %["'A"".""B'"] )
431
- end
432
-
433
- it 'shouldn\'t quote or escape identifier if requested to not do' do
434
- quoted_type = PG::TextEncoder::Identifier.new elements_type: textenc_string,
435
- needs_quotation: false
436
- expect( quoted_type.encode(['a','b']) ).to eq( %[a.b] )
437
- expect( quoted_type.encode(%[a.b]) ).to eq( %[a.b] )
438
- end
439
- end
440
-
441
522
  context 'literal quotation' do
442
523
  it 'should quote and escape literals' do
443
524
  quoted_type = PG::TextEncoder::QuotedLiteral.new elements_type: textenc_string_array
444
525
  expect( quoted_type.encode(["'A\",","\\B'"]) ).to eq( %['{"''A\\",","\\\\B''"}'] )
445
526
  end
527
+
528
+ it 'should quote literals with correct character encoding' do
529
+ quoted_type = PG::TextEncoder::QuotedLiteral.new elements_type: textenc_string_array
530
+ v = quoted_type.encode(["Héllo"], "iso-8859-1")
531
+ expect( v.encoding ).to eq( Encoding::ISO_8859_1 )
532
+ expect( v ).to eq( %['{Héllo}'].encode(Encoding::ISO_8859_1) )
533
+ end
446
534
  end
447
535
  end
448
536
 
@@ -489,11 +577,22 @@ describe "PG::Type derivations" do
489
577
  expect( e.encode("xxxx") ).to eq("eHh4eA==")
490
578
  expect( e.encode("xxxxx") ).to eq("eHh4eHg=")
491
579
  expect( e.encode("\0\n\t") ).to eq("AAoJ")
580
+ expect( e.encode("(\xFBm") ).to eq("KPtt")
581
+ end
582
+
583
+ it 'should encode Strings as base64 with correct character encoding' do
584
+ e = PG::TextEncoder::ToBase64.new
585
+ v = e.encode("Héllo".encode("utf-16le"), "iso-8859-1")
586
+ expect( v ).to eq("SOlsbG8=")
587
+ expect( v.encoding ).to eq(Encoding::ISO_8859_1)
492
588
  end
493
589
 
494
590
  it "should encode Strings as base64 in BinaryDecoder" do
495
591
  e = PG::BinaryDecoder::ToBase64.new
496
592
  expect( e.decode("x") ).to eq("eA==")
593
+ v = e.decode("Héllo".encode("utf-16le"))
594
+ expect( v ).to eq("SADpAGwAbABvAA==")
595
+ expect( v.encoding ).to eq(Encoding::ASCII_8BIT)
497
596
  end
498
597
 
499
598
  it "should encode Integers as base64" do
@@ -517,6 +616,7 @@ describe "PG::Type derivations" do
517
616
  expect( e.decode("eHh4eA==") ).to eq("xxxx")
518
617
  expect( e.decode("eHh4eHg=") ).to eq("xxxxx")
519
618
  expect( e.decode("AAoJ") ).to eq("\0\n\t")
619
+ expect( e.decode("KPtt") ).to eq("(\xFBm")
520
620
  end
521
621
 
522
622
  it "should decode base64 in BinaryEncoder" do
@@ -579,6 +679,12 @@ describe "PG::Type derivations" do
579
679
  expect( encoder.encode([:xyz, 123, 2456, 34567, 456789, 5678901, [1,2,3], 12.1, "abcdefg", nil]) ).
580
680
  to eq("xyz\t123\t2456\t34567\t456789\t5678901\t[1, 2, 3]\t12.1\tabcdefg\t\\N\n")
581
681
  end
682
+
683
+ it 'should output a string with correct character encoding' do
684
+ v = encoder.encode(["Héllo"], "iso-8859-1")
685
+ expect( v.encoding ).to eq( Encoding::ISO_8859_1 )
686
+ expect( v ).to eq( "Héllo\n".encode(Encoding::ISO_8859_1) )
687
+ end
582
688
  end
583
689
 
584
690
  context "with TypeMapByClass" do
@@ -643,6 +749,12 @@ describe "PG::Type derivations" do
643
749
  it "should decode different types of Ruby objects" do
644
750
  expect( decoder.decode("123\t \0#\t#\n#\r#\\ \t234\t#\x01#\002\n".gsub("#", "\\"))).to eq( ["123", " \0\t\n\r\\ ", "234", "\x01\x02"] )
645
751
  end
752
+
753
+ it 'should respect input character encoding' do
754
+ v = decoder.decode("Héllo\n".encode("iso-8859-1")).first
755
+ expect( v.encoding ).to eq(Encoding::ISO_8859_1)
756
+ expect( v ).to eq("Héllo".encode("iso-8859-1"))
757
+ end
646
758
  end
647
759
  end
648
760
 
data/spec/pg_spec.rb CHANGED
@@ -7,7 +7,7 @@ require 'pg'
7
7
 
8
8
  describe PG do
9
9
 
10
- it "knows what version of the libpq library is loaded", :postgresql_91 do
10
+ it "knows what version of the libpq library is loaded" do
11
11
  expect( PG.library_version ).to be_an( Integer )
12
12
  expect( PG.library_version ).to be >= 90100
13
13
  end
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.18.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Granger
@@ -11,27 +11,32 @@ bindir: bin
11
11
  cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
- MIIDbDCCAlSgAwIBAgIBATANBgkqhkiG9w0BAQUFADA+MQwwCgYDVQQDDANnZWQx
14
+ MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQUFADA+MQwwCgYDVQQDDANnZWQx
15
15
  GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
16
- HhcNMTQwMzE5MDQzNTI2WhcNMTUwMzE5MDQzNTI2WjA+MQwwCgYDVQQDDANnZWQx
16
+ HhcNMTcwOTI3MDAzMDQ0WhcNMTgwOTI3MDAzMDQ0WjA+MQwwCgYDVQQDDANnZWQx
17
17
  GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
18
- ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDb92mkyYwuGBg1oRxt2tkH
19
- +Uo3LAsaL/APBfSLzy8o3+B3AUHKCjMUaVeBoZdWtMHB75X3VQlvXfZMyBxj59Vo
20
- cDthr3zdao4HnyrzAIQf7BO5Y8KBwVD+yyXCD/N65TTwqsQnO3ie7U5/9ut1rnNr
21
- OkOzAscMwkfQxBkXDzjvAWa6UF4c5c9kR/T79iA21kDx9+bUMentU59aCJtUcbxa
22
- 7kcKJhPEYsk4OdxR9q2dphNMFDQsIdRO8rywX5FRHvcb+qnXC17RvxLHtOjysPtp
23
- EWsYoZMxyCDJpUqbwoeiM+tAHoz2ABMv3Ahie3Qeb6+MZNAtMmaWfBx3dg2u+/WN
24
- AgMBAAGjdTBzMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBSZ0hCV
25
- qoHr122fGKelqffzEQBhszAcBgNVHREEFTATgRFnZWRARmFlcmllTVVELm9yZzAc
26
- BgNVHRIEFTATgRFnZWRARmFlcmllTVVELm9yZzANBgkqhkiG9w0BAQUFAAOCAQEA
27
- TuL1Bzl6TBs1YEzEubFHb9XAPgehWzzUudjDKzTRd+uyZmxnomBqTCQjT5ucNRph
28
- 3jZ6bhLNooLQxTjIuHodeGcEMHZdt4Yi7SyPmw5Nry12z6wrDp+5aGps3HsE5WsQ
29
- Zq2EuyEOc96g31uoIvjNdieKs+1kE+K+dJDjtw+wTH2i63P7r6N/NfPPXpxsFquo
30
- wcYRRrHdR7GhdJeT+V8Q8Bi5bglCUGdx+8scMgkkePc98k9osQHypbACmzO+Bqkv
31
- c7ZKPJcWBv0sm81+FCZXNACn2f9jfF8OQinxVs0O052KbGuEQaaiGIYeuuwQE2q6
32
- ggcrPfcYeTwWlfZPu2LrBg==
18
+ ggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC/JWGRHO+USzR97vXjkFgt
19
+ 83qeNf2KHkcvrRTSnR64i6um/ziin0I0oX23H7VYrDJC9A/uoUa5nGRJS5Zw/+wW
20
+ ENcvWVZS4iUzi4dsYJGY6yEOsXh2CcF46+QevV8iE+UmbkU75V7Dy1JCaUOyizEt
21
+ TH5UHsOtUU7k9TYARt/TgYZKuaoAMZZd5qyVqhF1vV+7/Qzmp89NGflXf2xYP26a
22
+ 4MAX2qqKX/FKXqmFO+AGsbwYTEds1mksBF3fGsFgsQWxftG8GfZQ9+Cyu2+l1eOw
23
+ cZ+lPcg834G9DrqW2zhqUoLr1MTly4pqxYGb7XoDhoR7dd1kFE2a067+DzWC/ADt
24
+ +QkcqWUm5oh1fN0eqr7NsZlVJDulFgdiiYPQiIN7UNsii4Wc9aZqBoGcYfBeQNPZ
25
+ soo/6za/bWajOKUmDhpqvaiRv9EDpVLzuj53uDoukMMwxCMfgb04+ckQ0t2G7wqc
26
+ /D+K9JW9DDs3Yjgv9k4h7YMhW5gftosd+NkNC/+Y2CkCAwEAAaN1MHMwCQYDVR0T
27
+ BAIwADALBgNVHQ8EBAMCBLAwHQYDVR0OBBYEFHKN/nkRusdqCJEuq3lgB3fJvyTg
28
+ MBwGA1UdEQQVMBOBEWdlZEBGYWVyaWVNVUQub3JnMBwGA1UdEgQVMBOBEWdlZEBG
29
+ YWVyaWVNVUQub3JnMA0GCSqGSIb3DQEBBQUAA4IBgQB/qyi5pCjK8ceoKalfVAjS
30
+ vG64FEnLnD1bm39T5UaFIRmo+abZtfpg2QhwKvPbPjOicau2+m+MDQ2Cc3tgyaC3
31
+ dZxcP6w8APFg4AId09uWAZKf0xajvBMS2aOz8Bbmag6fwqRRkTMqsNYnmqcF7aRT
32
+ DuEzbEMfaOUYjU9RuB48vr4q8yRft0ww+3jq5iwNkrX1buL2pwBbyvgms6D/BV41
33
+ MaTVMjsHqJUwU2xVfhGtxGAWAer5S1HGYHkbio6mGVtiie0uWjmnzi7ppIlMr48a
34
+ 7BNTsoZ+/JRk3iQWmmNsyFT7xfqBKye7cH11BX8V8P4MeGB5YWlMI+Myj5DZY3fQ
35
+ st2AGD4rb1l0ia7PfubcBThSIdz61eCb8gRi/RiZZwb3/7+eyEncLJzt2Ob9fGSF
36
+ X0qdrKi+2aZZ0NGuFj9AItBsVmAvkBGIpX4TEKQp5haEbPpmaqO5nIIhV26PXmyT
37
+ OMKv6pWsoS81vw5KAGBmfX8nht/Py90DQrbRvakATGI=
33
38
  -----END CERTIFICATE-----
34
- date: 2015-01-03 00:00:00.000000000 Z
39
+ date: 2018-01-10 00:00:00.000000000 Z
35
40
  dependencies:
36
41
  - !ruby/object:Gem::Dependency
37
42
  name: hoe-mercurial
@@ -53,14 +58,14 @@ dependencies:
53
58
  requirements:
54
59
  - - "~>"
55
60
  - !ruby/object:Gem::Version
56
- version: '0.6'
61
+ version: '0.9'
57
62
  type: :development
58
63
  prerelease: false
59
64
  version_requirements: !ruby/object:Gem::Requirement
60
65
  requirements:
61
66
  - - "~>"
62
67
  - !ruby/object:Gem::Version
63
- version: '0.6'
68
+ version: '0.9'
64
69
  - !ruby/object:Gem::Dependency
65
70
  name: hoe-highline
66
71
  requirement: !ruby/object:Gem::Requirement
@@ -76,79 +81,99 @@ dependencies:
76
81
  - !ruby/object:Gem::Version
77
82
  version: '0.2'
78
83
  - !ruby/object:Gem::Dependency
79
- name: rdoc
84
+ name: rake-compiler
80
85
  requirement: !ruby/object:Gem::Requirement
81
86
  requirements:
82
87
  - - "~>"
83
88
  - !ruby/object:Gem::Version
84
- version: '4.0'
89
+ version: '1.0'
85
90
  type: :development
86
91
  prerelease: false
87
92
  version_requirements: !ruby/object:Gem::Requirement
88
93
  requirements:
89
94
  - - "~>"
90
95
  - !ruby/object:Gem::Version
91
- version: '4.0'
96
+ version: '1.0'
92
97
  - !ruby/object:Gem::Dependency
93
- name: rake-compiler
98
+ name: rake-compiler-dock
94
99
  requirement: !ruby/object:Gem::Requirement
95
100
  requirements:
96
101
  - - "~>"
97
102
  - !ruby/object:Gem::Version
98
- version: '0.9'
103
+ version: '0.6'
104
+ - - ">="
105
+ - !ruby/object:Gem::Version
106
+ version: 0.6.2
99
107
  type: :development
100
108
  prerelease: false
101
109
  version_requirements: !ruby/object:Gem::Requirement
102
110
  requirements:
103
111
  - - "~>"
104
112
  - !ruby/object:Gem::Version
105
- version: '0.9'
113
+ version: '0.6'
114
+ - - ">="
115
+ - !ruby/object:Gem::Version
116
+ version: 0.6.2
106
117
  - !ruby/object:Gem::Dependency
107
- name: hoe
118
+ name: hoe-bundler
108
119
  requirement: !ruby/object:Gem::Requirement
109
120
  requirements:
110
121
  - - "~>"
111
122
  - !ruby/object:Gem::Version
112
- version: '3.12'
123
+ version: '1.0'
113
124
  type: :development
114
125
  prerelease: false
115
126
  version_requirements: !ruby/object:Gem::Requirement
116
127
  requirements:
117
128
  - - "~>"
118
129
  - !ruby/object:Gem::Version
119
- version: '3.12'
130
+ version: '1.0'
120
131
  - !ruby/object:Gem::Dependency
121
- name: hoe-bundler
132
+ name: rspec
122
133
  requirement: !ruby/object:Gem::Requirement
123
134
  requirements:
124
135
  - - "~>"
125
136
  - !ruby/object:Gem::Version
126
- version: '1.0'
137
+ version: '3.5'
127
138
  type: :development
128
139
  prerelease: false
129
140
  version_requirements: !ruby/object:Gem::Requirement
130
141
  requirements:
131
142
  - - "~>"
132
143
  - !ruby/object:Gem::Version
133
- version: '1.0'
144
+ version: '3.5'
134
145
  - !ruby/object:Gem::Dependency
135
- name: rspec
146
+ name: rdoc
147
+ requirement: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - "~>"
150
+ - !ruby/object:Gem::Version
151
+ version: '5.1'
152
+ type: :development
153
+ prerelease: false
154
+ version_requirements: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - "~>"
157
+ - !ruby/object:Gem::Version
158
+ version: '5.1'
159
+ - !ruby/object:Gem::Dependency
160
+ name: hoe
136
161
  requirement: !ruby/object:Gem::Requirement
137
162
  requirements:
138
163
  - - "~>"
139
164
  - !ruby/object:Gem::Version
140
- version: '3.0'
165
+ version: '3.16'
141
166
  type: :development
142
167
  prerelease: false
143
168
  version_requirements: !ruby/object:Gem::Requirement
144
169
  requirements:
145
170
  - - "~>"
146
171
  - !ruby/object:Gem::Version
147
- version: '3.0'
172
+ version: '3.16'
148
173
  description: |-
149
174
  Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
150
175
 
151
- It works with {PostgreSQL 8.4 and later}[http://www.postgresql.org/support/versioning/].
176
+ It works with {PostgreSQL 9.2 and later}[http://www.postgresql.org/support/versioning/].
152
177
 
153
178
  A small example usage:
154
179
 
@@ -160,7 +185,7 @@ description: |-
160
185
  conn = PG.connect( dbname: 'sales' )
161
186
  conn.exec( "SELECT * FROM pg_stat_activity" ) do |result|
162
187
  puts " PID | User | Query"
163
- result.each do |row|
188
+ result.each do |row|
164
189
  puts " %7d | %-16s | %s " %
165
190
  row.values_at('procpid', 'usename', 'current_query')
166
191
  end
@@ -255,24 +280,6 @@ files:
255
280
  - lib/pg/text_decoder.rb
256
281
  - lib/pg/text_encoder.rb
257
282
  - lib/pg/type_map_by_column.rb
258
- - sample/array_insert.rb
259
- - sample/async_api.rb
260
- - sample/async_copyto.rb
261
- - sample/async_mixed.rb
262
- - sample/check_conn.rb
263
- - sample/copyfrom.rb
264
- - sample/copyto.rb
265
- - sample/cursor.rb
266
- - sample/disk_usage_report.rb
267
- - sample/issue-119.rb
268
- - sample/losample.rb
269
- - sample/minimal-testcase.rb
270
- - sample/notify_wait.rb
271
- - sample/pg_statistics.rb
272
- - sample/replication_monitor.rb
273
- - sample/test_binary_values.rb
274
- - sample/wal_shipper.rb
275
- - sample/warehouse_partitions.rb
276
283
  - spec/data/expected_trace.out
277
284
  - spec/data/random_binary_data
278
285
  - spec/helpers.rb
@@ -289,17 +296,11 @@ files:
289
296
  - spec/pg_spec.rb
290
297
  homepage: https://bitbucket.org/ged/ruby-pg
291
298
  licenses:
292
- - BSD
293
- - Ruby
294
- - GPL
299
+ - BSD-3-Clause
295
300
  metadata: {}
296
301
  post_install_message:
297
302
  rdoc_options:
298
- - "-f"
299
- - fivefish
300
- - "-t"
301
- - 'pg: The Ruby Interface to PostgreSQL'
302
- - "-m"
303
+ - "--main"
303
304
  - README.rdoc
304
305
  require_paths:
305
306
  - lib
@@ -307,7 +308,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
307
308
  requirements:
308
309
  - - ">="
309
310
  - !ruby/object:Gem::Version
310
- version: 1.8.7
311
+ version: 2.0.0
311
312
  required_rubygems_version: !ruby/object:Gem::Requirement
312
313
  requirements:
313
314
  - - ">="
@@ -315,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
315
316
  version: '0'
316
317
  requirements: []
317
318
  rubyforge_project:
318
- rubygems_version: 2.4.5
319
+ rubygems_version: 2.7.3
319
320
  signing_key:
320
321
  specification_version: 4
321
322
  summary: Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/]
metadata.gz.sig CHANGED
Binary file
@@ -1,20 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'pg'
4
-
5
- c = PG.connect( dbname: 'test' )
6
-
7
- # this one works:
8
- c.exec( "DROP TABLE IF EXISTS foo" )
9
- c.exec( "CREATE TABLE foo (strings character varying[]);" )
10
-
11
- # But using a prepared statement works:
12
- c.set_error_verbosity( PG::PQERRORS_VERBOSE )
13
- c.prepare( 'stmt', "INSERT INTO foo VALUES ($1);" )
14
-
15
- # This won't work
16
- #c.exec_prepared( 'stmt', ["ARRAY['this','that']"] )
17
-
18
- # but this will:
19
- c.exec_prepared( 'stmt', ["{'this','that'}"] )
20
-