pg 0.18.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
-