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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data/BSDL +2 -2
- data/ChangeLog +1221 -4
- data/History.rdoc +130 -0
- data/Manifest.txt +0 -18
- data/README-Windows.rdoc +15 -26
- data/README.rdoc +16 -10
- data/Rakefile +32 -23
- data/Rakefile.cross +56 -38
- data/ext/errorcodes.def +33 -0
- data/ext/errorcodes.txt +15 -1
- data/ext/extconf.rb +27 -35
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +27 -39
- data/ext/pg.c +19 -51
- data/ext/pg.h +22 -79
- data/ext/pg_binary_decoder.c +3 -1
- data/ext/pg_binary_encoder.c +14 -12
- data/ext/pg_coder.c +31 -10
- data/ext/pg_connection.c +350 -263
- data/ext/pg_copy_coder.c +34 -4
- data/ext/pg_result.c +27 -25
- data/ext/pg_text_decoder.c +9 -10
- data/ext/pg_text_encoder.c +93 -73
- data/ext/pg_type_map.c +20 -13
- data/ext/pg_type_map_by_column.c +7 -7
- data/ext/pg_type_map_by_mri_type.c +2 -2
- data/ext/pg_type_map_in_ruby.c +4 -7
- data/ext/util.c +3 -3
- data/ext/util.h +1 -1
- data/lib/pg/basic_type_mapping.rb +69 -42
- data/lib/pg/connection.rb +89 -38
- data/lib/pg/result.rb +10 -5
- data/lib/pg/text_decoder.rb +12 -3
- data/lib/pg/text_encoder.rb +8 -0
- data/lib/pg.rb +18 -10
- data/spec/helpers.rb +9 -16
- data/spec/pg/basic_type_mapping_spec.rb +58 -4
- data/spec/pg/connection_spec.rb +477 -217
- data/spec/pg/result_spec.rb +14 -7
- data/spec/pg/type_map_by_class_spec.rb +2 -2
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- data/spec/pg/type_spec.rb +145 -33
- data/spec/pg_spec.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +67 -66
- metadata.gz.sig +0 -0
- data/sample/array_insert.rb +0 -20
- data/sample/async_api.rb +0 -106
- data/sample/async_copyto.rb +0 -39
- data/sample/async_mixed.rb +0 -56
- data/sample/check_conn.rb +0 -21
- data/sample/copyfrom.rb +0 -81
- data/sample/copyto.rb +0 -19
- data/sample/cursor.rb +0 -21
- data/sample/disk_usage_report.rb +0 -186
- data/sample/issue-119.rb +0 -94
- data/sample/losample.rb +0 -69
- data/sample/minimal-testcase.rb +0 -17
- data/sample/notify_wait.rb +0 -72
- data/sample/pg_statistics.rb +0 -294
- data/sample/replication_monitor.rb +0 -231
- data/sample/test_binary_values.rb +0 -33
- data/sample/wal_shipper.rb +0 -434
- data/sample/warehouse_partitions.rb +0 -320
data/spec/pg/result_spec.rb
CHANGED
@@ -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"
|
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
|
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
|
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
|
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
|
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"
|
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 =
|
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[
|
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',
|
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',
|
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
|
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
|
-
|
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"
|
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.
|
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
|
-
|
14
|
+
MIIEbDCCAtSgAwIBAgIBATANBgkqhkiG9w0BAQUFADA+MQwwCgYDVQQDDANnZWQx
|
15
15
|
GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
|
16
|
-
|
16
|
+
HhcNMTcwOTI3MDAzMDQ0WhcNMTgwOTI3MDAzMDQ0WjA+MQwwCgYDVQQDDANnZWQx
|
17
17
|
GTAXBgoJkiaJk/IsZAEZFglGYWVyaWVNVUQxEzARBgoJkiaJk/IsZAEZFgNvcmcw
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
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:
|
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.
|
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.
|
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:
|
84
|
+
name: rake-compiler
|
80
85
|
requirement: !ruby/object:Gem::Requirement
|
81
86
|
requirements:
|
82
87
|
- - "~>"
|
83
88
|
- !ruby/object:Gem::Version
|
84
|
-
version: '
|
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: '
|
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.
|
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.
|
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: '
|
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: '
|
130
|
+
version: '1.0'
|
120
131
|
- !ruby/object:Gem::Dependency
|
121
|
-
name:
|
132
|
+
name: rspec
|
122
133
|
requirement: !ruby/object:Gem::Requirement
|
123
134
|
requirements:
|
124
135
|
- - "~>"
|
125
136
|
- !ruby/object:Gem::Version
|
126
|
-
version: '
|
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: '
|
144
|
+
version: '3.5'
|
134
145
|
- !ruby/object:Gem::Dependency
|
135
|
-
name:
|
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.
|
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.
|
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
|
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
|
-
|
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
|
-
- "
|
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:
|
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.
|
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
|
data/sample/array_insert.rb
DELETED
@@ -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
|
-
|