pg 1.1.0 → 1.2.2
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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +101 -1
- data/Manifest.txt +3 -2
- data/README-Windows.rdoc +4 -4
- data/README.ja.rdoc +1 -2
- data/README.rdoc +43 -8
- data/Rakefile +7 -5
- data/Rakefile.cross +46 -44
- data/ext/errorcodes.def +68 -0
- data/ext/errorcodes.txt +19 -2
- data/ext/extconf.rb +6 -6
- data/ext/pg.c +138 -99
- data/ext/pg.h +33 -26
- data/ext/pg_binary_decoder.c +20 -16
- data/ext/pg_binary_encoder.c +13 -12
- data/ext/pg_coder.c +5 -5
- data/ext/pg_connection.c +413 -321
- data/ext/pg_copy_coder.c +5 -3
- data/ext/pg_record_coder.c +490 -0
- data/ext/pg_result.c +282 -128
- data/ext/pg_text_decoder.c +14 -8
- data/ext/pg_text_encoder.c +180 -48
- data/ext/pg_tuple.c +14 -6
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +4 -4
- data/ext/pg_type_map_by_class.c +4 -3
- data/ext/pg_type_map_by_column.c +7 -6
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -2
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/{util.c → pg_util.c} +5 -5
- data/ext/{util.h → pg_util.h} +0 -0
- data/lib/pg.rb +5 -5
- data/lib/pg/basic_type_mapping.rb +79 -16
- data/lib/pg/binary_decoder.rb +1 -0
- data/lib/pg/coder.rb +22 -1
- data/lib/pg/connection.rb +2 -2
- data/lib/pg/constants.rb +1 -0
- data/lib/pg/exceptions.rb +1 -0
- data/lib/pg/result.rb +13 -1
- data/lib/pg/text_decoder.rb +2 -3
- data/lib/pg/text_encoder.rb +8 -18
- data/lib/pg/type_map_by_column.rb +2 -1
- data/spec/helpers.rb +18 -16
- data/spec/pg/basic_type_mapping_spec.rb +151 -14
- data/spec/pg/connection_spec.rb +162 -54
- data/spec/pg/result_spec.rb +193 -3
- data/spec/pg/tuple_spec.rb +55 -2
- data/spec/pg/type_map_by_column_spec.rb +5 -1
- data/spec/pg/type_spec.rb +180 -6
- metadata +39 -45
- metadata.gz.sig +0 -0
data/spec/pg/tuple_spec.rb
CHANGED
@@ -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!(:
|
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
|
-
|
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.
|
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
|
716
|
-
mt = Marshal.dump(
|
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(
|
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.
|
4
|
+
version: 1.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Granger
|
@@ -11,32 +11,30 @@ bindir: bin
|
|
11
11
|
cert_chain:
|
12
12
|
- |
|
13
13
|
-----BEGIN CERTIFICATE-----
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
+
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
X0qdrKi+2aZZ0NGuFj9AItBsVmAvkBGIpX4TEKQp5haEbPpmaqO5nIIhV26PXmyT
|
37
|
-
OMKv6pWsoS81vw5KAGBmfX8nht/Py90DQrbRvakATGI=
|
14
|
+
MIID+DCCAmCgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAiMSAwHgYDVQQDDBdnZWQv
|
15
|
+
REM9RmFlcmllTVVEL0RDPW9yZzAeFw0xOTEyMjQyMDE5NTFaFw0yMDEyMjMyMDE5
|
16
|
+
NTFaMCIxIDAeBgNVBAMMF2dlZC9EQz1GYWVyaWVNVUQvREM9b3JnMIIBojANBgkq
|
17
|
+
hkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvyVhkRzvlEs0fe7145BYLfN6njX9ih5H
|
18
|
+
L60U0p0euIurpv84op9CNKF9tx+1WKwyQvQP7qFGuZxkSUuWcP/sFhDXL1lWUuIl
|
19
|
+
M4uHbGCRmOshDrF4dgnBeOvkHr1fIhPlJm5FO+Vew8tSQmlDsosxLUx+VB7DrVFO
|
20
|
+
5PU2AEbf04GGSrmqADGWXeaslaoRdb1fu/0M5qfPTRn5V39sWD9umuDAF9qqil/x
|
21
|
+
Sl6phTvgBrG8GExHbNZpLARd3xrBYLEFsX7RvBn2UPfgsrtvpdXjsHGfpT3IPN+B
|
22
|
+
vQ66lts4alKC69TE5cuKasWBm+16A4aEe3XdZBRNmtOu/g81gvwA7fkJHKllJuaI
|
23
|
+
dXzdHqq+zbGZVSQ7pRYHYomD0IiDe1DbIouFnPWmagaBnGHwXkDT2bKKP+s2v21m
|
24
|
+
ozilJg4aar2okb/RA6VS87o+d7g6LpDDMMQjH4G9OPnJENLdhu8KnPw/ivSVvQw7
|
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
|
38
36
|
-----END CERTIFICATE-----
|
39
|
-
date:
|
37
|
+
date: 2020-01-08 00:00:00.000000000 Z
|
40
38
|
dependencies:
|
41
39
|
- !ruby/object:Gem::Dependency
|
42
40
|
name: hoe-mercurial
|
@@ -100,20 +98,14 @@ dependencies:
|
|
100
98
|
requirements:
|
101
99
|
- - "~>"
|
102
100
|
- !ruby/object:Gem::Version
|
103
|
-
version: '0
|
104
|
-
- - ">="
|
105
|
-
- !ruby/object:Gem::Version
|
106
|
-
version: 0.6.2
|
101
|
+
version: '1.0'
|
107
102
|
type: :development
|
108
103
|
prerelease: false
|
109
104
|
version_requirements: !ruby/object:Gem::Requirement
|
110
105
|
requirements:
|
111
106
|
- - "~>"
|
112
107
|
- !ruby/object:Gem::Version
|
113
|
-
version: '0
|
114
|
-
- - ">="
|
115
|
-
- !ruby/object:Gem::Version
|
116
|
-
version: 0.6.2
|
108
|
+
version: '1.0'
|
117
109
|
- !ruby/object:Gem::Dependency
|
118
110
|
name: hoe-bundler
|
119
111
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,14 +154,14 @@ dependencies:
|
|
162
154
|
requirements:
|
163
155
|
- - "~>"
|
164
156
|
- !ruby/object:Gem::Version
|
165
|
-
version: '3.
|
157
|
+
version: '3.20'
|
166
158
|
type: :development
|
167
159
|
prerelease: false
|
168
160
|
version_requirements: !ruby/object:Gem::Requirement
|
169
161
|
requirements:
|
170
162
|
- - "~>"
|
171
163
|
- !ruby/object:Gem::Version
|
172
|
-
version: '3.
|
164
|
+
version: '3.20'
|
173
165
|
description: |-
|
174
166
|
Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/].
|
175
167
|
|
@@ -215,6 +207,7 @@ extra_rdoc_files:
|
|
215
207
|
- ext/pg_connection.c
|
216
208
|
- ext/pg_copy_coder.c
|
217
209
|
- ext/pg_errors.c
|
210
|
+
- ext/pg_record_coder.c
|
218
211
|
- ext/pg_result.c
|
219
212
|
- ext/pg_text_decoder.c
|
220
213
|
- ext/pg_text_encoder.c
|
@@ -226,7 +219,7 @@ extra_rdoc_files:
|
|
226
219
|
- ext/pg_type_map_by_mri_type.c
|
227
220
|
- ext/pg_type_map_by_oid.c
|
228
221
|
- ext/pg_type_map_in_ruby.c
|
229
|
-
- ext/
|
222
|
+
- ext/pg_util.c
|
230
223
|
files:
|
231
224
|
- ".gemtest"
|
232
225
|
- BSDL
|
@@ -256,6 +249,7 @@ files:
|
|
256
249
|
- ext/pg_connection.c
|
257
250
|
- ext/pg_copy_coder.c
|
258
251
|
- ext/pg_errors.c
|
252
|
+
- ext/pg_record_coder.c
|
259
253
|
- ext/pg_result.c
|
260
254
|
- ext/pg_text_decoder.c
|
261
255
|
- ext/pg_text_encoder.c
|
@@ -267,8 +261,8 @@ files:
|
|
267
261
|
- ext/pg_type_map_by_mri_type.c
|
268
262
|
- ext/pg_type_map_by_oid.c
|
269
263
|
- ext/pg_type_map_in_ruby.c
|
270
|
-
- ext/
|
271
|
-
- ext/
|
264
|
+
- ext/pg_util.c
|
265
|
+
- ext/pg_util.h
|
272
266
|
- ext/vc/pg.sln
|
273
267
|
- ext/vc/pg_18/pg.vcproj
|
274
268
|
- ext/vc/pg_19/pg_19.vcproj
|
@@ -300,10 +294,11 @@ files:
|
|
300
294
|
- spec/pg/type_map_spec.rb
|
301
295
|
- spec/pg/type_spec.rb
|
302
296
|
- spec/pg_spec.rb
|
303
|
-
homepage: https://
|
297
|
+
homepage: https://github.com/ged/ruby-pg
|
304
298
|
licenses:
|
305
|
-
- BSD-
|
306
|
-
metadata:
|
299
|
+
- BSD-2-Clause
|
300
|
+
metadata:
|
301
|
+
homepage_uri: https://github.com/ged/ruby-pg
|
307
302
|
post_install_message:
|
308
303
|
rdoc_options:
|
309
304
|
- "--main"
|
@@ -314,15 +309,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
314
309
|
requirements:
|
315
310
|
- - ">="
|
316
311
|
- !ruby/object:Gem::Version
|
317
|
-
version: 2.
|
312
|
+
version: '2.2'
|
318
313
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
319
314
|
requirements:
|
320
315
|
- - ">="
|
321
316
|
- !ruby/object:Gem::Version
|
322
317
|
version: '0'
|
323
318
|
requirements: []
|
324
|
-
|
325
|
-
rubygems_version: 2.7.6
|
319
|
+
rubygems_version: 3.0.6
|
326
320
|
signing_key:
|
327
321
|
specification_version: 4
|
328
322
|
summary: Pg is the Ruby interface to the {PostgreSQL RDBMS}[http://www.postgresql.org/]
|