pg 1.1.4-x64-mingw32 → 1.2.0-x64-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 (61) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/ChangeLog +0 -6595
  5. data/History.rdoc +63 -0
  6. data/Manifest.txt +3 -2
  7. data/README-Windows.rdoc +4 -4
  8. data/README.ja.rdoc +1 -2
  9. data/README.rdoc +43 -8
  10. data/Rakefile +3 -3
  11. data/Rakefile.cross +6 -3
  12. data/ext/errorcodes.def +64 -0
  13. data/ext/errorcodes.txt +18 -2
  14. data/ext/extconf.rb +6 -6
  15. data/ext/pg.c +132 -95
  16. data/ext/pg.h +20 -18
  17. data/ext/pg_binary_decoder.c +9 -9
  18. data/ext/pg_binary_encoder.c +13 -12
  19. data/ext/pg_coder.c +5 -5
  20. data/ext/pg_connection.c +388 -298
  21. data/ext/pg_copy_coder.c +5 -3
  22. data/ext/pg_record_coder.c +490 -0
  23. data/ext/pg_result.c +269 -123
  24. data/ext/pg_text_decoder.c +14 -8
  25. data/ext/pg_text_encoder.c +180 -48
  26. data/ext/pg_tuple.c +14 -6
  27. data/ext/pg_type_map.c +1 -1
  28. data/ext/pg_type_map_all_strings.c +4 -4
  29. data/ext/pg_type_map_by_class.c +4 -3
  30. data/ext/pg_type_map_by_column.c +7 -6
  31. data/ext/pg_type_map_by_mri_type.c +1 -1
  32. data/ext/pg_type_map_by_oid.c +3 -2
  33. data/ext/pg_type_map_in_ruby.c +1 -1
  34. data/ext/{util.c → pg_util.c} +5 -5
  35. data/ext/{util.h → pg_util.h} +0 -0
  36. data/lib/2.2/pg_ext.so +0 -0
  37. data/lib/2.3/pg_ext.so +0 -0
  38. data/lib/2.4/pg_ext.so +0 -0
  39. data/lib/2.5/pg_ext.so +0 -0
  40. data/lib/2.6/pg_ext.so +0 -0
  41. data/lib/libpq.dll +0 -0
  42. data/lib/pg.rb +2 -3
  43. data/lib/pg/basic_type_mapping.rb +79 -16
  44. data/lib/pg/binary_decoder.rb +1 -0
  45. data/lib/pg/coder.rb +22 -1
  46. data/lib/pg/connection.rb +2 -2
  47. data/lib/pg/constants.rb +1 -0
  48. data/lib/pg/exceptions.rb +1 -0
  49. data/lib/pg/result.rb +13 -1
  50. data/lib/pg/text_decoder.rb +2 -3
  51. data/lib/pg/text_encoder.rb +8 -18
  52. data/lib/pg/type_map_by_column.rb +2 -1
  53. data/spec/helpers.rb +10 -8
  54. data/spec/pg/basic_type_mapping_spec.rb +150 -13
  55. data/spec/pg/connection_spec.rb +89 -50
  56. data/spec/pg/result_spec.rb +193 -3
  57. data/spec/pg/tuple_spec.rb +55 -2
  58. data/spec/pg/type_map_by_column_spec.rb +5 -1
  59. data/spec/pg/type_spec.rb +180 -6
  60. metadata +27 -25
  61. metadata.gz.sig +2 -3
@@ -8,10 +8,22 @@ require 'objspace'
8
8
  describe PG::Tuple do
9
9
  let!(:typemap) { PG::BasicTypeMapForResults.new(@conn) }
10
10
  let!(:result2x2) { @conn.exec( "VALUES(1, 'a'), (2, 'b')" ) }
11
- let!(:result2x3cast) { @conn.exec( "SELECT * FROM (VALUES(1, TRUE, '3'), (2, FALSE, '4')) AS m (a, b, b)" ).map_types!(typemap) }
11
+ let!(:result2x2sym) { @conn.exec( "VALUES(1, 'a'), (2, 'b')" ).field_names_as(:symbol) }
12
+ let!(:result2x3cast) do
13
+ @conn.exec( "SELECT * FROM (VALUES(1, TRUE, '3'), (2, FALSE, '4')) AS m (a, b, b)" )
14
+ .map_types!(typemap)
15
+ end
16
+ let!(:result2x3symcast) do
17
+ @conn.exec( "SELECT * FROM (VALUES(1, TRUE, '3'), (2, FALSE, '4')) AS m (a, b, b)" )
18
+ .map_types!(typemap)
19
+ .field_names_as(:symbol)
20
+ end
12
21
  let!(:tuple0) { result2x2.tuple(0) }
22
+ let!(:tuple0sym) { result2x2sym.tuple(0) }
13
23
  let!(:tuple1) { result2x2.tuple(1) }
24
+ let!(:tuple1sym) { result2x2sym.tuple(1) }
14
25
  let!(:tuple2) { result2x3cast.tuple(0) }
26
+ let!(:tuple2sym) { result2x3symcast.tuple(0) }
15
27
  let!(:tuple3) { str = Marshal.dump(result2x3cast.tuple(1)); Marshal.load(str) }
16
28
  let!(:tuple_empty) { PG::Tuple.new }
17
29
 
@@ -51,9 +63,19 @@ describe PG::Tuple do
51
63
  expect( tuple0["column2"] ).to eq( "a" )
52
64
  expect( tuple2["a"] ).to eq( 1 )
53
65
  expect( tuple2["b"] ).to eq( "3" )
66
+ expect( tuple0[:b] ).to be_nil
54
67
  expect( tuple0["x"] ).to be_nil
55
68
  end
56
69
 
70
+ it "supports hash like access with symbols" do
71
+ expect( tuple0sym[:column1] ).to eq( "1" )
72
+ expect( tuple0sym[:column2] ).to eq( "a" )
73
+ expect( tuple2sym[:a] ).to eq( 1 )
74
+ expect( tuple2sym[:b] ).to eq( "3" )
75
+ expect( tuple2sym["b"] ).to be_nil
76
+ expect( tuple0sym[:x] ).to be_nil
77
+ end
78
+
57
79
  it "casts lazy and caches result" do
58
80
  a = []
59
81
  deco = Class.new(PG::SimpleDecoder) do
@@ -138,6 +160,12 @@ describe PG::Tuple do
138
160
  expect{ tuple_empty.each }.to raise_error(TypeError)
139
161
  end
140
162
 
163
+ it "can be used as an enumerator with symbols" do
164
+ expect( tuple0sym.each ).to be_kind_of(Enumerator)
165
+ expect( tuple0sym.each.to_a ).to eq( [[:column1, "1"], [:column2, "a"]] )
166
+ expect( tuple2sym.each.to_a ).to eq( [[:a, 1], [:b, true], [:b, "3"]] )
167
+ end
168
+
141
169
  it "can be used with block" do
142
170
  a = []
143
171
  tuple0.each do |*v|
@@ -174,16 +202,30 @@ describe PG::Tuple do
174
202
 
175
203
  it "responds to key?" do
176
204
  expect( tuple1.key?("column1") ).to eq( true )
205
+ expect( tuple1.key?(:column1) ).to eq( false )
177
206
  expect( tuple1.key?("other") ).to eq( false )
178
207
  expect( tuple1.has_key?("column1") ).to eq( true )
179
208
  expect( tuple1.has_key?("other") ).to eq( false )
180
209
  end
181
210
 
211
+ it "responds to key? as symbol" do
212
+ expect( tuple1sym.key?(:column1) ).to eq( true )
213
+ expect( tuple1sym.key?("column1") ).to eq( false )
214
+ expect( tuple1sym.key?(:other) ).to eq( false )
215
+ expect( tuple1sym.has_key?(:column1) ).to eq( true )
216
+ expect( tuple1sym.has_key?(:other) ).to eq( false )
217
+ end
218
+
182
219
  it "responds to keys" do
183
220
  expect( tuple0.keys ).to eq( ["column1", "column2"] )
184
221
  expect( tuple2.keys ).to eq( ["a", "b", "b"] )
185
222
  end
186
223
 
224
+ it "responds to keys as symbol" do
225
+ expect( tuple0sym.keys ).to eq( [:column1, :column2] )
226
+ expect( tuple2sym.keys ).to eq( [:a, :b, :b] )
227
+ end
228
+
187
229
  describe "each_key" do
188
230
  it "can be used as an enumerator" do
189
231
  expect( tuple0.each_key ).to be_kind_of(Enumerator)
@@ -208,12 +250,22 @@ describe PG::Tuple do
208
250
 
209
251
  it "responds to index" do
210
252
  expect( tuple0.index("column1") ).to eq( 0 )
253
+ expect( tuple0.index(:column1) ).to eq( nil )
211
254
  expect( tuple0.index("column2") ).to eq( 1 )
212
255
  expect( tuple0.index("x") ).to eq( nil )
213
256
  expect( tuple2.index("a") ).to eq( 0 )
214
257
  expect( tuple2.index("b") ).to eq( 2 )
215
258
  end
216
259
 
260
+ it "responds to index with symbol" do
261
+ expect( tuple0sym.index(:column1) ).to eq( 0 )
262
+ expect( tuple0sym.index("column1") ).to eq( nil )
263
+ expect( tuple0sym.index(:column2) ).to eq( 1 )
264
+ expect( tuple0sym.index(:x) ).to eq( nil )
265
+ expect( tuple2sym.index(:a) ).to eq( 0 )
266
+ expect( tuple2sym.index(:b) ).to eq( 2 )
267
+ end
268
+
217
269
  it "can be used as Enumerable" do
218
270
  expect( tuple0.to_a ).to eq( [["column1", "1"], ["column2", "a"]] )
219
271
  expect( tuple1.to_a ).to eq( [["column1", "2"], ["column2", "b"]] )
@@ -222,7 +274,7 @@ describe PG::Tuple do
222
274
  end
223
275
 
224
276
  it "can be marshaled" do
225
- [tuple0, tuple1, tuple2, tuple3].each do |t1|
277
+ [tuple0, tuple1, tuple2, tuple3, tuple0sym, tuple2sym].each do |t1|
226
278
  str = Marshal.dump(t1)
227
279
  t2 = Marshal.load(str)
228
280
 
@@ -253,6 +305,7 @@ describe PG::Tuple do
253
305
  it "should override #inspect" do
254
306
  expect( tuple1.inspect ).to eq('#<PG::Tuple column1: "2", column2: "b">')
255
307
  expect( tuple2.inspect ).to eq('#<PG::Tuple a: 1, b: true, b: "3">')
308
+ expect( tuple2sym.inspect ).to eq('#<PG::Tuple a: 1, b: true, b: "3">')
256
309
  expect{ tuple_empty.inspect }.to raise_error(TypeError)
257
310
  end
258
311
 
@@ -38,7 +38,11 @@ describe PG::TypeMapByColumn do
38
38
  pass_through_type,
39
39
  nil
40
40
  ] )
41
- expect( cm.inspect ).to eq( "#<PG::TypeMapByColumn INT4:0 TEXT:0 FLOAT4:0 pass_through:1 nil>" )
41
+ end
42
+
43
+ it "should respond to inspect" do
44
+ cm = PG::TypeMapByColumn.new( [textdec_int, textenc_string, textdec_float, pass_through_type, PG::TextEncoder::Float.new, nil] )
45
+ expect( cm.inspect ).to eq( "#<PG::TypeMapByColumn INT4:TD TEXT:TE FLOAT4:TD pass_through:BD PG::TextEncoder::Float:TE nil>" )
42
46
  end
43
47
 
44
48
  it "should retrieve it's oids" do
data/spec/pg/type_spec.rb CHANGED
@@ -12,6 +12,7 @@ describe "PG::Type derivations" do
12
12
  let!(:textdec_boolean) { PG::TextDecoder::Boolean.new }
13
13
  let!(:textenc_float) { PG::TextEncoder::Float.new }
14
14
  let!(:textdec_float) { PG::TextDecoder::Float.new }
15
+ let!(:textenc_numeric) { PG::TextEncoder::Numeric.new }
15
16
  let!(:textenc_string) { PG::TextEncoder::String.new }
16
17
  let!(:textdec_string) { PG::TextDecoder::String.new }
17
18
  let!(:textenc_timestamp) { PG::TextEncoder::TimestampWithoutTimeZone.new }
@@ -254,6 +255,11 @@ describe "PG::Type derivations" do
254
255
  expect( textdec_string.decode( nil )).to be_nil
255
256
  expect( textdec_int.decode( nil )).to be_nil
256
257
  end
258
+
259
+ it "should be defined on an encoder but not on a decoder instance" do
260
+ expect( textdec_int.respond_to?(:decode) ).to be_truthy
261
+ expect( textenc_int.respond_to?(:decode) ).to be_falsey
262
+ end
257
263
  end
258
264
 
259
265
  describe '#encode' do
@@ -304,12 +310,73 @@ describe "PG::Type derivations" do
304
310
  end
305
311
  end
306
312
 
313
+ it "should encode floats" do
314
+ expect( textenc_float.encode(0) ).to eq( "0.0" )
315
+ expect( textenc_float.encode(-1) ).to eq( "-1.0" )
316
+ expect( textenc_float.encode(-1.234567890123456789) ).to eq( "-1.234567890123457" )
317
+ expect( textenc_float.encode(9) ).to eq( "9.0" )
318
+ expect( textenc_float.encode(10) ).to eq( "10.0" )
319
+ expect( textenc_float.encode(-99) ).to eq( "-99.0" )
320
+ expect( textenc_float.encode(-100) ).to eq( "-100.0" )
321
+ expect( textenc_float.encode(999) ).to eq( "999.0" )
322
+ expect( textenc_float.encode(-1000) ).to eq( "-1000.0" )
323
+ expect( textenc_float.encode(1234.567890123456789) ).to eq( "1234.567890123457" )
324
+ expect( textenc_float.encode(-9999) ).to eq( "-9999.0" )
325
+ expect( textenc_float.encode(10000) ).to eq( "10000.0" )
326
+ expect( textenc_float.encode(99999) ).to eq( "99999.0" )
327
+ expect( textenc_float.encode(-100000) ).to eq( "-100000.0" )
328
+ expect( textenc_float.encode(-999999) ).to eq( "-999999.0" )
329
+ expect( textenc_float.encode(1000000) ).to eq( "1000000.0" )
330
+ expect( textenc_float.encode(9999999) ).to eq( "9999999.0" )
331
+ expect( textenc_float.encode(-100000000000000) ).to eq( "-100000000000000.0" )
332
+ expect( textenc_float.encode(123456789012345) ).to eq( "123456789012345.0" )
333
+ expect( textenc_float.encode(-999999999999999) ).to eq( "-999999999999999.0" )
334
+ expect( textenc_float.encode(1000000000000000) ).to eq( "1e15" )
335
+ expect( textenc_float.encode(-1234567890123456) ).to eq( "-1.234567890123456e15" )
336
+ expect( textenc_float.encode(9999999999999999) ).to eq( "1e16" )
337
+
338
+ expect( textenc_float.encode(-0.0) ).to eq( "0.0" )
339
+ expect( textenc_float.encode(0.1) ).to eq( "0.1" )
340
+ expect( textenc_float.encode(0.1234567890123456789) ).to eq( "0.1234567890123457" )
341
+ expect( textenc_float.encode(-0.9) ).to eq( "-0.9" )
342
+ expect( textenc_float.encode(-0.01234567890123456789) ).to eq( "-0.01234567890123457" )
343
+ expect( textenc_float.encode(0.09) ).to eq( "0.09" )
344
+ expect( textenc_float.encode(0.001234567890123456789) ).to eq( "0.001234567890123457" )
345
+ expect( textenc_float.encode(-0.009) ).to eq( "-0.009" )
346
+ expect( textenc_float.encode(-0.0001234567890123456789) ).to eq( "-0.0001234567890123457" )
347
+ expect( textenc_float.encode(0.0009) ).to eq( "0.0009" )
348
+ expect( textenc_float.encode(0.00001) ).to eq( "1e-5" )
349
+ expect( textenc_float.encode(0.00001234567890123456789) ).to eq( "1.234567890123457e-5" )
350
+ expect( textenc_float.encode(-0.00009) ).to eq( "-9e-5" )
351
+ expect( textenc_float.encode(-0.11) ).to eq( "-0.11" )
352
+ expect( textenc_float.encode(10.11) ).to eq( "10.11" )
353
+ expect( textenc_float.encode(-1.234567890123456789E-280) ).to eq( "-1.234567890123457e-280" )
354
+ expect( textenc_float.encode(-1.234567890123456789E280) ).to eq( "-1.234567890123457e280" )
355
+ expect( textenc_float.encode(9876543210987654321E280) ).to eq( "9.87654321098765e298" )
356
+ expect( textenc_float.encode(9876543210987654321E-400) ).to eq( "0.0" )
357
+ expect( textenc_float.encode(9876543210987654321E400) ).to eq( "Infinity" )
358
+ end
359
+
307
360
  it "should encode special floats equally to Float#to_s" do
308
361
  expect( textenc_float.encode(Float::INFINITY) ).to eq( Float::INFINITY.to_s )
309
362
  expect( textenc_float.encode(-Float::INFINITY) ).to eq( (-Float::INFINITY).to_s )
310
363
  expect( textenc_float.encode(-Float::NAN) ).to eq( Float::NAN.to_s )
311
364
  end
312
365
 
366
+ it "should encode various inputs to numeric format" do
367
+ expect( textenc_numeric.encode(0) ).to eq( "0" )
368
+ expect( textenc_numeric.encode(1) ).to eq( "1" )
369
+ expect( textenc_numeric.encode(-12345678901234567890123) ).to eq( "-12345678901234567890123" )
370
+ expect( textenc_numeric.encode(0.0) ).to eq( "0.0" )
371
+ expect( textenc_numeric.encode(1.0) ).to eq( "1.0" )
372
+ expect( textenc_numeric.encode(-1.23456789012e45) ).to eq( "-1.23456789012e45" )
373
+ expect( textenc_numeric.encode(Float::NAN) ).to eq( Float::NAN.to_s )
374
+ expect( textenc_numeric.encode(BigDecimal(0)) ).to eq( "0.0" )
375
+ expect( textenc_numeric.encode(BigDecimal(1)) ).to eq( "1.0" )
376
+ expect( textenc_numeric.encode(BigDecimal("-12345678901234567890.1234567")) ).to eq( "-12345678901234567890.1234567" )
377
+ expect( textenc_numeric.encode(" 123 ") ).to eq( " 123 " )
378
+ end
379
+
313
380
  it "encodes binary string to bytea" do
314
381
  expect( textenc_bytea.encode("\x00\x01\x02\x03\xef".b) ).to eq( "\\x00010203ef" )
315
382
  end
@@ -376,6 +443,11 @@ describe "PG::Type derivations" do
376
443
  expect( textenc_string.encode( nil )).to be_nil
377
444
  expect( textenc_int.encode( nil )).to be_nil
378
445
  end
446
+
447
+ it "should be defined on a decoder but not on an encoder instance" do
448
+ expect( textenc_int.respond_to?(:encode) ).to be_truthy
449
+ expect( textdec_int.respond_to?(:encode) ).to be_falsey
450
+ end
379
451
  end
380
452
 
381
453
  it "should be possible to marshal encoders" do
@@ -392,7 +464,7 @@ describe "PG::Type derivations" do
392
464
 
393
465
  it "should respond to to_h" do
394
466
  expect( textenc_int.to_h ).to eq( {
395
- name: 'Integer', oid: 23, format: 0
467
+ name: 'Integer', oid: 23, format: 0, flags: 0
396
468
  } )
397
469
  end
398
470
 
@@ -624,7 +696,7 @@ describe "PG::Type derivations" do
624
696
  expect( textenc_int_array.encode(['1',['2'],'3']) ).to eq( %[{1,{2},3}] )
625
697
  end
626
698
  it 'encodes an array of float8 with sub arrays' do
627
- expect( textenc_float_array.encode([1000.11,[-0.00221,[3.31,-441]],[nil,6.61],-7.71]) ).to match(Regexp.new(%[^{1.0001*E+*03,{-2.2*E-*03,{3.3*E+*00,-4.4*E+*02}},{NULL,6.6*E+*00},-7.7*E+*00}$].gsub(/([\.\+\{\}\,])/, "\\\\\\1").gsub(/\*/, "\\d*")))
699
+ expect( textenc_float_array.encode([1000.11,[-0.00000221,[3.31,-441]],[nil,6.61],-7.71]) ).to match(Regexp.new(%[^{1000.1*,{-2.2*e-*6,{3.3*,-441.0}},{NULL,6.6*},-7.7*}$].gsub(/([\.\+\{\}\,])/, "\\\\\\1").gsub(/\*/, "\\d*")))
628
700
  end
629
701
  end
630
702
  context 'two dimensional arrays' do
@@ -712,15 +784,15 @@ describe "PG::Type derivations" do
712
784
  expect( lt.to_h ).to eq( textenc_int_array.to_h )
713
785
  end
714
786
 
715
- it "should be possible to marshal encoders" do
716
- mt = Marshal.dump(textdec_int_array)
787
+ it "should be possible to marshal decoders" do
788
+ mt = Marshal.dump(textdec_string_array_raise)
717
789
  lt = Marshal.load(mt)
718
- expect( lt.to_h ).to eq( textdec_int_array.to_h )
790
+ expect( lt.to_h ).to eq( textdec_string_array_raise.to_h )
719
791
  end
720
792
 
721
793
  it "should respond to to_h" do
722
794
  expect( textenc_int_array.to_h ).to eq( {
723
- name: nil, oid: 0, format: 0,
795
+ name: nil, oid: 0, format: 0, flags: 0,
724
796
  elements_type: textenc_int, needs_quotation: false, delimiter: ','
725
797
  } )
726
798
  end
@@ -946,4 +1018,106 @@ describe "PG::Type derivations" do
946
1018
  end
947
1019
  end
948
1020
  end
1021
+
1022
+ describe PG::RecordCoder do
1023
+ describe PG::TextEncoder::Record do
1024
+ context "with default typemap" do
1025
+ let!(:encoder) do
1026
+ PG::TextEncoder::Record.new
1027
+ end
1028
+
1029
+ it "should encode different types of Ruby objects" do
1030
+ expect( encoder.encode([:xyz, 123, 2456, 34567, 456789, 5678901, [1,2,3], 12.1, "abcdefg", nil]) ).
1031
+ to eq('("xyz","123","2456","34567","456789","5678901","[1, 2, 3]","12.1","abcdefg",)')
1032
+ end
1033
+
1034
+ it 'should output a string with correct character encoding' do
1035
+ v = encoder.encode(["Héllo"], "iso-8859-1")
1036
+ expect( v.encoding ).to eq( Encoding::ISO_8859_1 )
1037
+ expect( v ).to eq( '("Héllo")'.encode(Encoding::ISO_8859_1) )
1038
+ end
1039
+ end
1040
+
1041
+ context "with TypeMapByClass" do
1042
+ let!(:tm) do
1043
+ tm = PG::TypeMapByClass.new
1044
+ tm[Integer] = textenc_int
1045
+ tm[Float] = intenc_incrementer
1046
+ tm[Array] = PG::TextEncoder::Array.new elements_type: textenc_string
1047
+ tm
1048
+ end
1049
+ let!(:encoder) do
1050
+ PG::TextEncoder::Record.new type_map: tm
1051
+ end
1052
+
1053
+ it "should have reasonable default values" do
1054
+ expect( encoder.name ).to be_nil
1055
+ end
1056
+
1057
+ it "copies all attributes with #dup" do
1058
+ encoder.name = "test"
1059
+ encoder.type_map = PG::TypeMapByColumn.new []
1060
+ encoder2 = encoder.dup
1061
+ expect( encoder.object_id ).to_not eq( encoder2.object_id )
1062
+ expect( encoder2.name ).to eq( "test" )
1063
+ expect( encoder2.type_map ).to be_a_kind_of( PG::TypeMapByColumn )
1064
+ end
1065
+
1066
+ describe '#encode' do
1067
+ it "should encode different types of Ruby objects" do
1068
+ expect( encoder.encode([]) ).to eq("()")
1069
+ expect( encoder.encode(["a"]) ).to eq('("a")')
1070
+ expect( encoder.encode([:xyz, 123, 2456, 34567, 456789, 5678901, [1,2,3], 12.1, "abcdefg", nil]) ).
1071
+ to eq('("xyz","123","2456","34567","456789","5678901","{1,2,3}","13 ","abcdefg",)')
1072
+ end
1073
+
1074
+ it "should escape special characters" do
1075
+ expect( encoder.encode([" \"\t\n\\\r"]) ).to eq("(\" \"\"\t\n##\r\")".gsub("#", "\\"))
1076
+ end
1077
+ end
1078
+ end
1079
+ end
1080
+
1081
+ describe PG::TextDecoder::Record do
1082
+ context "with default typemap" do
1083
+ let!(:decoder) do
1084
+ PG::TextDecoder::Record.new
1085
+ end
1086
+
1087
+ describe '#decode' do
1088
+ it "should decode composite text format to array of strings" do
1089
+ expect( decoder.decode('("fuzzy dice",,"",42,)') ).to eq( ["fuzzy dice",nil, "", "42", nil] )
1090
+ end
1091
+
1092
+ it 'should respect input character encoding' do
1093
+ v = decoder.decode("(Héllo)".encode("iso-8859-1")).first
1094
+ expect( v.encoding ).to eq(Encoding::ISO_8859_1)
1095
+ expect( v ).to eq("Héllo".encode("iso-8859-1"))
1096
+ end
1097
+
1098
+ it 'should raise an error on malformed input' do
1099
+ expect{ decoder.decode('') }.to raise_error(ArgumentError, /"" - Missing left parenthesis/)
1100
+ expect{ decoder.decode('(') }.to raise_error(ArgumentError, /"\(" - Unexpected end of input/)
1101
+ expect{ decoder.decode('(\\') }.to raise_error(ArgumentError, /"\(\\" - Unexpected end of input/)
1102
+ expect{ decoder.decode('()x') }.to raise_error(ArgumentError, /"\(\)x" - Junk after right parenthesis/)
1103
+ end
1104
+ end
1105
+ end
1106
+
1107
+ context "with TypeMapByColumn" do
1108
+ let!(:tm) do
1109
+ PG::TypeMapByColumn.new [textdec_int, textdec_string, intdec_incrementer, nil]
1110
+ end
1111
+ let!(:decoder) do
1112
+ PG::TextDecoder::Record.new type_map: tm
1113
+ end
1114
+
1115
+ describe '#decode' do
1116
+ it "should decode different types of Ruby objects" do
1117
+ expect( decoder.decode("(123,\" #,#\n#\r#\\ \",234,#\x01#\002)".gsub("#", "\\"))).to eq( [123, " ,\n\r\\ ", 235, "\x01\x02"] )
1118
+ end
1119
+ end
1120
+ end
1121
+ end
1122
+ end
949
1123
  end
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: 1.1.4
4
+ version: 1.2.0
5
5
  platform: x64-mingw32
6
6
  authors:
7
7
  - Michael Granger
@@ -11,9 +11,9 @@ bindir: bin
11
11
  cert_chain:
12
12
  - |
13
13
  -----BEGIN CERTIFICATE-----
14
- MIIENDCCApygAwIBAgIBATANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBdnZWQv
15
- REM9RmFlcmllTVVEL0RDPW9yZzAeFw0xODExMjAxODI5NTlaFw0xOTExMjAxODI5
16
- NTlaMCIxIDAeBgNVBAMMF2dlZC9EQz1GYWVyaWVNVUQvREM9b3JnMIIBojANBgkq
14
+ MIID+DCCAmCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBdnZWQv
15
+ REM9RmFlcmllTVVEL0RDPW9yZzAeFw0xOTEyMjQyMDE5NTFaFw0yMDEyMjMyMDE5
16
+ NTFaMCIxIDAeBgNVBAMMF2dlZC9EQz1GYWVyaWVNVUQvREM9b3JnMIIBojANBgkq
17
17
  hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvyVhkRzvlEs0fe7145BYLfN6njX9ih5H
18
18
  L60U0p0euIurpv84op9CNKF9tx+1WKwyQvQP7qFGuZxkSUuWcP/sFhDXL1lWUuIl
19
19
  M4uHbGCRmOshDrF4dgnBeOvkHr1fIhPlJm5FO+Vew8tSQmlDsosxLUx+VB7DrVFO
@@ -22,20 +22,19 @@ cert_chain:
22
22
  vQ66lts4alKC69TE5cuKasWBm+16A4aEe3XdZBRNmtOu/g81gvwA7fkJHKllJuaI
23
23
  dXzdHqq+zbGZVSQ7pRYHYomD0IiDe1DbIouFnPWmagaBnGHwXkDT2bKKP+s2v21m
24
24
  ozilJg4aar2okb/RA6VS87o+d7g6LpDDMMQjH4G9OPnJENLdhu8KnPw/ivSVvQw7
25
- N2I4L/ZOIe2DIVuYH7aLHfjZDQv/mNgpAgMBAAGjdTBzMAkGA1UdEwQCMAAwCwYD
26
- VR0PBAQDAgSwMB0GA1UdDgQWBBRyjf55EbrHagiRLqt5YAd3yb8k4DAcBgNVHREE
27
- FTATgRFnZWRARmFlcmllTVVELm9yZzAcBgNVHRIEFTATgRFnZWRARmFlcmllTVVE
28
- Lm9yZzANBgkqhkiG9w0BAQsFAAOCAYEAP9Ffkvg4e8CjIWi8SykQ8oJSS8jbmbgF
29
- abke3vXWLG6V9kFiObuJd5wZRBluJANu7bEtjgc3fFaGVP2XxVdCpVjNbmMDg4Qp
30
- ovvczP53X6pQP2RSZgxF6Lblvy8y11RziUTVRG/Z2aJHsElo6gI7vQznE/OSDrhC
31
- gEhr8uaIUt7D+HZWRbU0+MkKPpL5uMqaFuJbqXEvSwPTuUuYkDfNfsjQO7ruWBac
32
- bxHCrvpZ6Tijc0nrlyXi6gPOCLeaqhau2xFnlvKgELwsGYSoKBJyDwqtQ5kwrOlU
33
- tkSyLrfZ+RZcH535Hyvif7ZxB0v5OxXXoec+N2vrUsEUMRDL9dg4/WFdN8hIOixF
34
- 3IPKpZ1ho0Ya5q7yhygtBK9/NBFHw+nbJjcltfPDBXleRe8u73gnQo8AZIhStYSP
35
- v4qqqa27Bs468d6SoPxjSm8a2mM9HZ4OdWhq4tFsbTeXDVquCfi64OTEaTt2xQdR
36
- JnC4lpJfCP6aCXa5h2XAQfPSH636cQap
25
+ N2I4L/ZOIe2DIVuYH7aLHfjZDQv/mNgpAgMBAAGjOTA3MAkGA1UdEwQCMAAwCwYD
26
+ VR0PBAQDAgSwMB0GA1UdDgQWBBRyjf55EbrHagiRLqt5YAd3yb8k4DANBgkqhkiG
27
+ 9w0BAQsFAAOCAYEAifxlz7x0EfT3fjhM520ZEIrWa+tLMuLKNefkY18u8tZnx4EX
28
+ Xxwh3tna3fvNfrOrdY5leIj1dbv4FTRg+gIBnIxAySqvpGvI/Axg5EdYbwninCLL
29
+ LAKCmRo+5QwaPMYN2zdHIjGrp8jg1neCo5zy6tVvyTv0DMI6FLrydVJYduMMDFSy
30
+ gQKR1rVOcCJtnBnLCF9+kKEUKohAHOmGsE7OBZFnjMIpH5yUDUVJKByv0gIipFt0
31
+ 1T6zff6oVU0w8WBiNKR381+6sF3wIZVnVY0XeJg6hNL+YecE8ILxLhHTmtT/BO0S
32
+ 3xPze9uXDR+iD6HYl8KU5QEg/dXFPhfQb512vVkTJDZvMcwu6PxDUjHFChLjAji/
33
+ AZXjg1C5E9znTkeUR8ieU9F1MOKoiH57a5lYSTI8Ga8PpsNXTxNeXc16Ob26CqrJ
34
+ 83uuAYSy65yXDGXXPVBeKPVnYrqp91pqpS5Nh7wfuiCrE8lgU8PATh7K4BV1UhAT
35
+ 0MHbAT42wTYkfUj3
37
36
  -----END CERTIFICATE-----
38
- date: 2019-01-09 00:00:00.000000000 Z
37
+ date: 2019-12-24 00:00:00.000000000 Z
39
38
  dependencies:
40
39
  - !ruby/object:Gem::Dependency
41
40
  name: hoe-mercurial
@@ -155,14 +154,14 @@ dependencies:
155
154
  requirements:
156
155
  - - "~>"
157
156
  - !ruby/object:Gem::Version
158
- version: '3.17'
157
+ version: '3.20'
159
158
  type: :development
160
159
  prerelease: false
161
160
  version_requirements: !ruby/object:Gem::Requirement
162
161
  requirements:
163
162
  - - "~>"
164
163
  - !ruby/object:Gem::Version
165
- version: '3.17'
164
+ version: '3.20'
166
165
  description: |-
167
166
  Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
168
167
 
@@ -207,6 +206,7 @@ extra_rdoc_files:
207
206
  - ext/pg_connection.c
208
207
  - ext/pg_copy_coder.c
209
208
  - ext/pg_errors.c
209
+ - ext/pg_record_coder.c
210
210
  - ext/pg_result.c
211
211
  - ext/pg_text_decoder.c
212
212
  - ext/pg_text_encoder.c
@@ -218,7 +218,7 @@ extra_rdoc_files:
218
218
  - ext/pg_type_map_by_mri_type.c
219
219
  - ext/pg_type_map_by_oid.c
220
220
  - ext/pg_type_map_in_ruby.c
221
- - ext/util.c
221
+ - ext/pg_util.c
222
222
  files:
223
223
  - ".gemtest"
224
224
  - BSDL
@@ -248,6 +248,7 @@ files:
248
248
  - ext/pg_connection.c
249
249
  - ext/pg_copy_coder.c
250
250
  - ext/pg_errors.c
251
+ - ext/pg_record_coder.c
251
252
  - ext/pg_result.c
252
253
  - ext/pg_text_decoder.c
253
254
  - ext/pg_text_encoder.c
@@ -259,8 +260,8 @@ files:
259
260
  - ext/pg_type_map_by_mri_type.c
260
261
  - ext/pg_type_map_by_oid.c
261
262
  - ext/pg_type_map_in_ruby.c
262
- - ext/util.c
263
- - ext/util.h
263
+ - ext/pg_util.c
264
+ - ext/pg_util.h
264
265
  - ext/vc/pg.sln
265
266
  - ext/vc/pg_18/pg.vcproj
266
267
  - ext/vc/pg_19/pg_19.vcproj
@@ -298,10 +299,11 @@ files:
298
299
  - spec/pg/type_map_spec.rb
299
300
  - spec/pg/type_spec.rb
300
301
  - spec/pg_spec.rb
301
- homepage: https://bitbucket.org/ged/ruby-pg
302
+ homepage: https://github.com/ged/ruby-pg
302
303
  licenses:
303
- - BSD-3-Clause
304
- metadata: {}
304
+ - BSD-2-Clause
305
+ metadata:
306
+ homepage_uri: https://github.com/ged/ruby-pg
305
307
  post_install_message:
306
308
  rdoc_options:
307
309
  - "--main"