pg 1.2.3-x86-mingw32 → 1.3.0.rc4-x86-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.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/.appveyor.yml +36 -0
- data/.gems +6 -0
- data/.github/workflows/binary-gems.yml +86 -0
- data/.github/workflows/source-gem.yml +130 -0
- data/.gitignore +13 -0
- data/.hgsigs +34 -0
- data/.hgtags +41 -0
- data/.irbrc +23 -0
- data/.pryrc +23 -0
- data/.tm_properties +21 -0
- data/.travis.yml +49 -0
- data/Gemfile +14 -0
- data/History.rdoc +77 -7
- data/Manifest.txt +0 -1
- data/README.rdoc +7 -6
- data/Rakefile +27 -138
- data/Rakefile.cross +6 -5
- data/certs/ged.pem +24 -0
- data/ext/errorcodes.def +8 -0
- data/ext/errorcodes.txt +3 -1
- data/ext/extconf.rb +91 -19
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -0
- data/ext/pg.c +59 -4
- data/ext/pg.h +18 -1
- data/ext/pg_coder.c +82 -28
- data/ext/pg_connection.c +676 -492
- data/ext/pg_copy_coder.c +45 -16
- data/ext/pg_record_coder.c +39 -11
- data/ext/pg_result.c +61 -31
- data/ext/pg_text_decoder.c +1 -1
- data/ext/pg_text_encoder.c +6 -6
- data/ext/pg_tuple.c +47 -21
- data/ext/pg_type_map.c +41 -8
- data/ext/pg_type_map_all_strings.c +14 -1
- data/ext/pg_type_map_by_class.c +49 -24
- data/ext/pg_type_map_by_column.c +64 -28
- data/ext/pg_type_map_by_mri_type.c +47 -18
- data/ext/pg_type_map_by_oid.c +52 -23
- data/ext/pg_type_map_in_ruby.c +50 -19
- data/ext/pg_util.c +2 -2
- data/lib/2.5/pg_ext.so +0 -0
- data/lib/2.6/pg_ext.so +0 -0
- data/lib/2.7/pg_ext.so +0 -0
- data/lib/3.0/pg_ext.so +0 -0
- data/lib/3.1/pg_ext.so +0 -0
- data/lib/pg/basic_type_map_based_on_result.rb +47 -0
- data/lib/pg/basic_type_map_for_queries.rb +193 -0
- data/lib/pg/basic_type_map_for_results.rb +81 -0
- data/lib/pg/basic_type_registry.rb +296 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +587 -58
- data/lib/pg/version.rb +4 -0
- data/lib/pg.rb +40 -27
- data/lib/x86-mingw32/libpq.dll +0 -0
- data/misc/openssl-pg-segfault.rb +31 -0
- data/misc/postgres/History.txt +9 -0
- data/misc/postgres/Manifest.txt +5 -0
- data/misc/postgres/README.txt +21 -0
- data/misc/postgres/Rakefile +21 -0
- data/misc/postgres/lib/postgres.rb +16 -0
- data/misc/ruby-pg/History.txt +9 -0
- data/misc/ruby-pg/Manifest.txt +5 -0
- data/misc/ruby-pg/README.txt +21 -0
- data/misc/ruby-pg/Rakefile +21 -0
- data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
- data/pg.gemspec +32 -0
- data/sample/array_insert.rb +20 -0
- data/sample/async_api.rb +106 -0
- data/sample/async_copyto.rb +39 -0
- data/sample/async_mixed.rb +56 -0
- data/sample/check_conn.rb +21 -0
- data/sample/copydata.rb +71 -0
- data/sample/copyfrom.rb +81 -0
- data/sample/copyto.rb +19 -0
- data/sample/cursor.rb +21 -0
- data/sample/disk_usage_report.rb +177 -0
- data/sample/issue-119.rb +94 -0
- data/sample/losample.rb +69 -0
- data/sample/minimal-testcase.rb +17 -0
- data/sample/notify_wait.rb +72 -0
- data/sample/pg_statistics.rb +285 -0
- data/sample/replication_monitor.rb +222 -0
- data/sample/test_binary_values.rb +33 -0
- data/sample/wal_shipper.rb +434 -0
- data/sample/warehouse_partitions.rb +311 -0
- data.tar.gz.sig +0 -0
- metadata +93 -233
- metadata.gz.sig +0 -0
- data/ChangeLog +0 -0
- data/lib/2.2/pg_ext.so +0 -0
- data/lib/2.3/pg_ext.so +0 -0
- data/lib/2.4/pg_ext.so +0 -0
- data/lib/pg/basic_type_mapping.rb +0 -522
- data/spec/data/expected_trace.out +0 -26
- data/spec/data/random_binary_data +0 -0
- data/spec/helpers.rb +0 -380
- data/spec/pg/basic_type_mapping_spec.rb +0 -630
- data/spec/pg/connection_spec.rb +0 -1949
- data/spec/pg/connection_sync_spec.rb +0 -41
- data/spec/pg/result_spec.rb +0 -681
- data/spec/pg/tuple_spec.rb +0 -333
- data/spec/pg/type_map_by_class_spec.rb +0 -138
- data/spec/pg/type_map_by_column_spec.rb +0 -226
- data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
- data/spec/pg/type_map_by_oid_spec.rb +0 -149
- data/spec/pg/type_map_in_ruby_spec.rb +0 -164
- data/spec/pg/type_map_spec.rb +0 -22
- data/spec/pg/type_spec.rb +0 -1123
- data/spec/pg_spec.rb +0 -50
@@ -1,630 +0,0 @@
|
|
1
|
-
# -*- rspec -*-
|
2
|
-
# encoding: utf-8
|
3
|
-
|
4
|
-
require_relative '../helpers'
|
5
|
-
|
6
|
-
require 'pg'
|
7
|
-
require 'time'
|
8
|
-
|
9
|
-
def restore_type(types)
|
10
|
-
[0, 1].each do |format|
|
11
|
-
[types].flatten.each do |type|
|
12
|
-
PG::BasicTypeRegistry.alias_type(format, "restore_#{type}", type)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
yield
|
16
|
-
ensure
|
17
|
-
[0, 1].each do |format|
|
18
|
-
[types].flatten.each do |type|
|
19
|
-
PG::BasicTypeRegistry.alias_type(format, type, "restore_#{type}")
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
describe 'Basic type mapping' do
|
25
|
-
|
26
|
-
describe PG::BasicTypeMapForQueries do
|
27
|
-
let!(:basic_type_mapping) do
|
28
|
-
PG::BasicTypeMapForQueries.new @conn
|
29
|
-
end
|
30
|
-
|
31
|
-
#
|
32
|
-
# Encoding Examples
|
33
|
-
#
|
34
|
-
|
35
|
-
it "should do basic param encoding" do
|
36
|
-
res = @conn.exec_params( "SELECT $1::int8, $2::float, $3, $4::TEXT",
|
37
|
-
[1, 2.1, true, "b"], nil, basic_type_mapping )
|
38
|
-
|
39
|
-
expect( res.values ).to eq( [
|
40
|
-
[ "1", "2.1", "t", "b" ],
|
41
|
-
] )
|
42
|
-
|
43
|
-
expect( result_typenames(res) ).to eq( ['bigint', 'double precision', 'boolean', 'text'] )
|
44
|
-
end
|
45
|
-
|
46
|
-
it "should do basic Time encoding" do
|
47
|
-
res = @conn.exec_params( "SELECT $1 AT TIME ZONE '-02'",
|
48
|
-
[Time.new(2019, 12, 8, 20, 38, 12.123, "-01:00")], nil, basic_type_mapping )
|
49
|
-
|
50
|
-
expect( res.values ).to eq( [[ "2019-12-08 23:38:12.123" ]] )
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should do basic param encoding of various float values" do
|
54
|
-
res = @conn.exec_params( "SELECT $1::float, $2::float, $3::float, $4::float, $5::float, $6::float, $7::float, $8::float, $9::float, $10::float, $11::float, $12::float",
|
55
|
-
[0, 7, 9, 0.1, 0.9, -0.11, 10.11,
|
56
|
-
9876543210987654321e-400,
|
57
|
-
9876543210987654321e400,
|
58
|
-
-1.234567890123456789e-280,
|
59
|
-
-1.234567890123456789e280,
|
60
|
-
9876543210987654321e280
|
61
|
-
], nil, basic_type_mapping )
|
62
|
-
|
63
|
-
expect( res.values[0][0, 9] ).to eq(
|
64
|
-
[ "0", "7", "9", "0.1", "0.9", "-0.11", "10.11", "0", "Infinity" ]
|
65
|
-
)
|
66
|
-
|
67
|
-
expect( res.values[0][9] ).to match( /^-1\.2345678901234\d*e\-280$/ )
|
68
|
-
expect( res.values[0][10] ).to match( /^-1\.2345678901234\d*e\+280$/ )
|
69
|
-
expect( res.values[0][11] ).to match( /^9\.8765432109876\d*e\+298$/ )
|
70
|
-
|
71
|
-
expect( result_typenames(res) ).to eq( ['double precision'] * 12 )
|
72
|
-
end
|
73
|
-
|
74
|
-
it "should do default array-as-array param encoding" do
|
75
|
-
expect( basic_type_mapping.encode_array_as).to eq(:array)
|
76
|
-
res = @conn.exec_params( "SELECT $1,$2,$3,$4,$5,$6", [
|
77
|
-
[1, 2, 3], # Integer -> bigint[]
|
78
|
-
[[1, 2], [3, nil]], # Integer two dimensions -> bigint[]
|
79
|
-
[1.11, 2.21], # Float -> double precision[]
|
80
|
-
['/,"'.gsub("/", "\\"), nil, 'abcäöü'], # String -> text[]
|
81
|
-
[BigDecimal("123.45")], # BigDecimal -> numeric[]
|
82
|
-
[IPAddr.new('1234::5678')], # IPAddr -> inet[]
|
83
|
-
], nil, basic_type_mapping )
|
84
|
-
|
85
|
-
expect( res.values ).to eq( [[
|
86
|
-
'{1,2,3}',
|
87
|
-
'{{1,2},{3,NULL}}',
|
88
|
-
'{1.11,2.21}',
|
89
|
-
'{"//,/"",NULL,abcäöü}'.gsub("/", "\\"),
|
90
|
-
'{123.45}',
|
91
|
-
'{1234::5678}',
|
92
|
-
]] )
|
93
|
-
|
94
|
-
expect( result_typenames(res) ).to eq( ['bigint[]', 'bigint[]', 'double precision[]', 'text[]', 'numeric[]', 'inet[]'] )
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should do default array-as-array param encoding with Time objects" do
|
98
|
-
res = @conn.exec_params( "SELECT $1", [
|
99
|
-
[Time.new(2019, 12, 8, 20, 38, 12.123, "-01:00")], # Time -> timestamptz[]
|
100
|
-
], nil, basic_type_mapping )
|
101
|
-
|
102
|
-
expect( res.values[0][0] ).to match( /\{\"2019-12-08 \d\d:38:12.123[+-]\d\d\"\}/ )
|
103
|
-
expect( result_typenames(res) ).to eq( ['timestamp with time zone[]'] )
|
104
|
-
end
|
105
|
-
|
106
|
-
it "should do array-as-json encoding" do
|
107
|
-
basic_type_mapping.encode_array_as = :json
|
108
|
-
expect( basic_type_mapping.encode_array_as).to eq(:json)
|
109
|
-
|
110
|
-
res = @conn.exec_params( "SELECT $1::JSON, $2::JSON", [
|
111
|
-
[1, {a: 5}, true, ["a", 2], [3.4, nil]],
|
112
|
-
['/,"'.gsub("/", "\\"), nil, 'abcäöü'],
|
113
|
-
], nil, basic_type_mapping )
|
114
|
-
|
115
|
-
expect( res.values ).to eq( [[
|
116
|
-
'[1,{"a":5},true,["a",2],[3.4,null]]',
|
117
|
-
'["//,/"",null,"abcäöü"]'.gsub("/", "\\"),
|
118
|
-
]] )
|
119
|
-
|
120
|
-
expect( result_typenames(res) ).to eq( ['json', 'json'] )
|
121
|
-
end
|
122
|
-
|
123
|
-
it "should do hash-as-json encoding" do
|
124
|
-
res = @conn.exec_params( "SELECT $1::JSON, $2::JSON", [
|
125
|
-
{a: 5, b: ["a", 2], c: nil},
|
126
|
-
{qu: '/,"'.gsub("/", "\\"), ni: nil, uml: 'abcäöü'},
|
127
|
-
], nil, basic_type_mapping )
|
128
|
-
|
129
|
-
expect( res.values ).to eq( [[
|
130
|
-
'{"a":5,"b":["a",2],"c":null}',
|
131
|
-
'{"qu":"//,/"","ni":null,"uml":"abcäöü"}'.gsub("/", "\\"),
|
132
|
-
]] )
|
133
|
-
|
134
|
-
expect( result_typenames(res) ).to eq( ['json', 'json'] )
|
135
|
-
end
|
136
|
-
|
137
|
-
describe "Record encoding" do
|
138
|
-
before :all do
|
139
|
-
@conn.exec("CREATE TYPE test_record1 AS (i int, d float, t text)")
|
140
|
-
@conn.exec("CREATE TYPE test_record2 AS (i int, r test_record1)")
|
141
|
-
end
|
142
|
-
|
143
|
-
after :all do
|
144
|
-
@conn.exec("DROP TYPE IF EXISTS test_record2 CASCADE")
|
145
|
-
@conn.exec("DROP TYPE IF EXISTS test_record1 CASCADE")
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should do array-as-record encoding" do
|
149
|
-
basic_type_mapping.encode_array_as = :record
|
150
|
-
expect( basic_type_mapping.encode_array_as).to eq(:record)
|
151
|
-
|
152
|
-
res = @conn.exec_params( "SELECT $1::test_record1, $2::test_record2, $3::text", [
|
153
|
-
[5, 3.4, "txt"],
|
154
|
-
[1, [2, 4.5, "bcd"]],
|
155
|
-
[4, 5, 6],
|
156
|
-
], nil, basic_type_mapping )
|
157
|
-
|
158
|
-
expect( res.values ).to eq( [[
|
159
|
-
'(5,3.4,txt)',
|
160
|
-
'(1,"(2,4.5,bcd)")',
|
161
|
-
'("4","5","6")',
|
162
|
-
]] )
|
163
|
-
|
164
|
-
expect( result_typenames(res) ).to eq( ['test_record1', 'test_record2', 'text'] )
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
it "should do bigdecimal param encoding" do
|
169
|
-
large = ('123456790'*10) << '.' << ('012345679')
|
170
|
-
res = @conn.exec_params( "SELECT $1::numeric,$2::numeric",
|
171
|
-
[BigDecimal('1'), BigDecimal(large)], nil, basic_type_mapping )
|
172
|
-
|
173
|
-
expect( res.values ).to eq( [
|
174
|
-
[ "1.0", large ],
|
175
|
-
] )
|
176
|
-
|
177
|
-
expect( result_typenames(res) ).to eq( ['numeric', 'numeric'] )
|
178
|
-
end
|
179
|
-
|
180
|
-
it "should do IPAddr param encoding" do
|
181
|
-
res = @conn.exec_params( "SELECT $1::inet,$2::inet,$3::cidr,$4::cidr",
|
182
|
-
['1.2.3.4', IPAddr.new('1234::5678'), '1.2.3.4', IPAddr.new('1234:5678::/32')], nil, basic_type_mapping )
|
183
|
-
|
184
|
-
expect( res.values ).to eq( [
|
185
|
-
[ '1.2.3.4', '1234::5678', '1.2.3.4/32', '1234:5678::/32'],
|
186
|
-
] )
|
187
|
-
|
188
|
-
expect( result_typenames(res) ).to eq( ['inet', 'inet', 'cidr', 'cidr'] )
|
189
|
-
end
|
190
|
-
|
191
|
-
it "should do array of string encoding on unknown classes" do
|
192
|
-
iv = Class.new do
|
193
|
-
def to_s
|
194
|
-
"abc"
|
195
|
-
end
|
196
|
-
end.new
|
197
|
-
res = @conn.exec_params( "SELECT $1", [
|
198
|
-
[iv, iv], # Unknown -> text[]
|
199
|
-
], nil, basic_type_mapping )
|
200
|
-
|
201
|
-
expect( res.values ).to eq( [[
|
202
|
-
'{abc,abc}',
|
203
|
-
]] )
|
204
|
-
|
205
|
-
expect( result_typenames(res) ).to eq( ['text[]'] )
|
206
|
-
end
|
207
|
-
|
208
|
-
end
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
describe PG::BasicTypeMapForResults do
|
213
|
-
let!(:basic_type_mapping) do
|
214
|
-
PG::BasicTypeMapForResults.new @conn
|
215
|
-
end
|
216
|
-
|
217
|
-
#
|
218
|
-
# Decoding Examples
|
219
|
-
#
|
220
|
-
|
221
|
-
it "should do OID based type conversions" do
|
222
|
-
res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, TRUE, '2013-06-30'::DATE, generate_series(4,5)" )
|
223
|
-
expect( res.map_types!(basic_type_mapping).values ).to eq( [
|
224
|
-
[ 1, 'a', 2.0, true, Date.new(2013,6,30), 4 ],
|
225
|
-
[ 1, 'a', 2.0, true, Date.new(2013,6,30), 5 ],
|
226
|
-
] )
|
227
|
-
end
|
228
|
-
|
229
|
-
#
|
230
|
-
# Decoding Examples text+binary format converters
|
231
|
-
#
|
232
|
-
|
233
|
-
describe "connection wide type mapping" do
|
234
|
-
before :each do
|
235
|
-
@conn.type_map_for_results = basic_type_mapping
|
236
|
-
end
|
237
|
-
|
238
|
-
after :each do
|
239
|
-
@conn.type_map_for_results = PG::TypeMapAllStrings.new
|
240
|
-
end
|
241
|
-
|
242
|
-
it "should do boolean type conversions" do
|
243
|
-
[1, 0].each do |format|
|
244
|
-
res = @conn.exec_params( "SELECT true::BOOLEAN, false::BOOLEAN, NULL::BOOLEAN", [], format )
|
245
|
-
expect( res.values ).to eq( [[true, false, nil]] )
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
it "should do binary type conversions" do
|
250
|
-
[1, 0].each do |format|
|
251
|
-
res = @conn.exec_params( "SELECT E'\\\\000\\\\377'::BYTEA", [], format )
|
252
|
-
expect( res.values ).to eq( [[["00ff"].pack("H*")]] )
|
253
|
-
expect( res.values[0][0].encoding ).to eq( Encoding::ASCII_8BIT ) if Object.const_defined? :Encoding
|
254
|
-
end
|
255
|
-
end
|
256
|
-
|
257
|
-
it "should do integer type conversions" do
|
258
|
-
[1, 0].each do |format|
|
259
|
-
res = @conn.exec_params( "SELECT -8999::INT2, -899999999::INT4, -8999999999999999999::INT8", [], format )
|
260
|
-
expect( res.values ).to eq( [[-8999, -899999999, -8999999999999999999]] )
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
it "should do string type conversions" do
|
265
|
-
@conn.internal_encoding = 'utf-8' if Object.const_defined? :Encoding
|
266
|
-
[1, 0].each do |format|
|
267
|
-
res = @conn.exec_params( "SELECT 'abcäöü'::TEXT", [], format )
|
268
|
-
expect( res.values ).to eq( [['abcäöü']] )
|
269
|
-
expect( res.values[0][0].encoding ).to eq( Encoding::UTF_8 ) if Object.const_defined? :Encoding
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
it "should do float type conversions" do
|
274
|
-
[1, 0].each do |format|
|
275
|
-
res = @conn.exec_params( "SELECT -8.999e3::FLOAT4,
|
276
|
-
8.999e10::FLOAT4,
|
277
|
-
-8999999999e-99::FLOAT8,
|
278
|
-
NULL::FLOAT4,
|
279
|
-
'NaN'::FLOAT4,
|
280
|
-
'Infinity'::FLOAT4,
|
281
|
-
'-Infinity'::FLOAT4
|
282
|
-
", [], format )
|
283
|
-
expect( res.getvalue(0,0) ).to be_within(1e-2).of(-8.999e3)
|
284
|
-
expect( res.getvalue(0,1) ).to be_within(1e5).of(8.999e10)
|
285
|
-
expect( res.getvalue(0,2) ).to be_within(1e-109).of(-8999999999e-99)
|
286
|
-
expect( res.getvalue(0,3) ).to be_nil
|
287
|
-
expect( res.getvalue(0,4) ).to be_nan
|
288
|
-
expect( res.getvalue(0,5) ).to eq( Float::INFINITY )
|
289
|
-
expect( res.getvalue(0,6) ).to eq( -Float::INFINITY )
|
290
|
-
end
|
291
|
-
end
|
292
|
-
|
293
|
-
it "should do text datetime without time zone type conversions" do
|
294
|
-
# for backward compat text timestamps without time zone are treated as local times
|
295
|
-
res = @conn.exec_params( "SELECT CAST('2013-12-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
296
|
-
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
297
|
-
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
298
|
-
CAST('294276-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
299
|
-
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
300
|
-
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], 0 )
|
301
|
-
expect( res.getvalue(0,0) ).to eq( Time.new(2013, 12, 31, 23, 58, 59) )
|
302
|
-
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.new(1913, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
303
|
-
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.new(-4713, 11, 24, 23, 58, 59.1231).iso8601(3) )
|
304
|
-
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.new(294276, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
305
|
-
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
306
|
-
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
307
|
-
end
|
308
|
-
|
309
|
-
[1, 0].each do |format|
|
310
|
-
it "should convert format #{format} timestamps per TimestampUtc" do
|
311
|
-
restore_type("timestamp") do
|
312
|
-
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampUtc
|
313
|
-
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
314
|
-
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
315
|
-
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
316
|
-
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
317
|
-
CAST('294276-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
318
|
-
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
319
|
-
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
|
320
|
-
expect( res.getvalue(0,0).iso8601(3) ).to eq( Time.utc(2013, 7, 31, 23, 58, 59).iso8601(3) )
|
321
|
-
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.utc(1913, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
322
|
-
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.utc(-4713, 11, 24, 23, 58, 59.1231).iso8601(3) )
|
323
|
-
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.utc(294276, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
324
|
-
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
325
|
-
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
326
|
-
end
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
[1, 0].each do |format|
|
331
|
-
it "should convert format #{format} timestamps per TimestampUtcToLocal" do
|
332
|
-
restore_type("timestamp") do
|
333
|
-
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampUtcToLocal
|
334
|
-
PG::BasicTypeRegistry.register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampUtcToLocal
|
335
|
-
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
336
|
-
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
337
|
-
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
338
|
-
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
339
|
-
CAST('294276-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
340
|
-
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
341
|
-
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
|
342
|
-
expect( res.getvalue(0,0).iso8601(3) ).to eq( Time.utc(2013, 7, 31, 23, 58, 59).getlocal.iso8601(3) )
|
343
|
-
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.utc(1913, 12, 31, 23, 58, 59.1231).getlocal.iso8601(3) )
|
344
|
-
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.utc(-4713, 11, 24, 23, 58, 59.1231).getlocal.iso8601(3) )
|
345
|
-
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.utc(294276, 12, 31, 23, 58, 59.1231).getlocal.iso8601(3) )
|
346
|
-
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
347
|
-
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
348
|
-
end
|
349
|
-
end
|
350
|
-
end
|
351
|
-
|
352
|
-
[1, 0].each do |format|
|
353
|
-
it "should convert format #{format} timestamps per TimestampLocal" do
|
354
|
-
restore_type("timestamp") do
|
355
|
-
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampLocal
|
356
|
-
PG::BasicTypeRegistry.register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampLocal
|
357
|
-
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
358
|
-
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59' AS TIMESTAMP WITHOUT TIME ZONE),
|
359
|
-
CAST('1913-12-31 23:58:59.1231' AS TIMESTAMP WITHOUT TIME ZONE),
|
360
|
-
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
361
|
-
CAST('294276-12-31 23:58:59.1231+03' AS TIMESTAMP WITHOUT TIME ZONE),
|
362
|
-
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
363
|
-
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
|
364
|
-
expect( res.getvalue(0,0).iso8601(3) ).to eq( Time.new(2013, 7, 31, 23, 58, 59).iso8601(3) )
|
365
|
-
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.new(1913, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
366
|
-
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.new(-4713, 11, 24, 23, 58, 59.1231).iso8601(3) )
|
367
|
-
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.new(294276, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
368
|
-
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
369
|
-
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
370
|
-
end
|
371
|
-
end
|
372
|
-
end
|
373
|
-
|
374
|
-
[0, 1].each do |format|
|
375
|
-
it "should convert format #{format} timestamps with time zone" do
|
376
|
-
res = @conn.exec_params( "SELECT CAST('2013-12-31 23:58:59+02' AS TIMESTAMP WITH TIME ZONE),
|
377
|
-
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITH TIME ZONE),
|
378
|
-
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITH TIME ZONE),
|
379
|
-
CAST('294276-12-31 23:58:59.1231+03' AS TIMESTAMP WITH TIME ZONE),
|
380
|
-
CAST('infinity' AS TIMESTAMP WITH TIME ZONE),
|
381
|
-
CAST('-infinity' AS TIMESTAMP WITH TIME ZONE)", [], format )
|
382
|
-
expect( res.getvalue(0,0) ).to be_within(1e-3).of( Time.new(2013, 12, 31, 23, 58, 59, "+02:00").getlocal )
|
383
|
-
expect( res.getvalue(0,1) ).to be_within(1e-3).of( Time.new(1913, 12, 31, 23, 58, 59.1231, "-03:00").getlocal )
|
384
|
-
expect( res.getvalue(0,2) ).to be_within(1e-3).of( Time.new(-4713, 11, 24, 23, 58, 59.1231, "-03:00").getlocal )
|
385
|
-
expect( res.getvalue(0,3) ).to be_within(1e-3).of( Time.new(294276, 12, 31, 23, 58, 59.1231, "+03:00").getlocal )
|
386
|
-
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
387
|
-
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
388
|
-
end
|
389
|
-
end
|
390
|
-
|
391
|
-
it "should do date type conversions" do
|
392
|
-
[0].each do |format|
|
393
|
-
res = @conn.exec_params( "SELECT CAST('2113-12-31' AS DATE),
|
394
|
-
CAST('1913-12-31' AS DATE),
|
395
|
-
CAST('infinity' AS DATE),
|
396
|
-
CAST('-infinity' AS DATE)", [], format )
|
397
|
-
expect( res.getvalue(0,0) ).to eq( Date.new(2113, 12, 31) )
|
398
|
-
expect( res.getvalue(0,1) ).to eq( Date.new(1913, 12, 31) )
|
399
|
-
expect( res.getvalue(0,2) ).to eq( 'infinity' )
|
400
|
-
expect( res.getvalue(0,3) ).to eq( '-infinity' )
|
401
|
-
end
|
402
|
-
end
|
403
|
-
|
404
|
-
it "should do numeric type conversions" do
|
405
|
-
[0].each do |format|
|
406
|
-
small = '123456790123.12'
|
407
|
-
large = ('123456790'*10) << '.' << ('012345679')
|
408
|
-
numerics = [
|
409
|
-
'1',
|
410
|
-
'1.0',
|
411
|
-
'1.2',
|
412
|
-
small,
|
413
|
-
large,
|
414
|
-
]
|
415
|
-
sql_numerics = numerics.map { |v| "CAST(#{v} AS numeric)" }
|
416
|
-
res = @conn.exec_params( "SELECT #{sql_numerics.join(',')}", [], format )
|
417
|
-
expect( res.getvalue(0,0) ).to eq( BigDecimal('1') )
|
418
|
-
expect( res.getvalue(0,1) ).to eq( BigDecimal('1') )
|
419
|
-
expect( res.getvalue(0,2) ).to eq( BigDecimal('1.2') )
|
420
|
-
expect( res.getvalue(0,3) ).to eq( BigDecimal(small) )
|
421
|
-
expect( res.getvalue(0,4) ).to eq( BigDecimal(large) )
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
it "should do JSON conversions", :postgresql_94 do
|
426
|
-
[0].each do |format|
|
427
|
-
['JSON', 'JSONB'].each do |type|
|
428
|
-
res = @conn.exec_params( "SELECT CAST('123' AS #{type}),
|
429
|
-
CAST('12.3' AS #{type}),
|
430
|
-
CAST('true' AS #{type}),
|
431
|
-
CAST('false' AS #{type}),
|
432
|
-
CAST('null' AS #{type}),
|
433
|
-
CAST('[1, \"a\", null]' AS #{type}),
|
434
|
-
CAST('{\"b\" : [2,3]}' AS #{type})", [], format )
|
435
|
-
expect( res.getvalue(0,0) ).to eq( 123 )
|
436
|
-
expect( res.getvalue(0,1) ).to be_within(0.1).of( 12.3 )
|
437
|
-
expect( res.getvalue(0,2) ).to eq( true )
|
438
|
-
expect( res.getvalue(0,3) ).to eq( false )
|
439
|
-
expect( res.getvalue(0,4) ).to eq( nil )
|
440
|
-
expect( res.getvalue(0,5) ).to eq( [1, "a", nil] )
|
441
|
-
expect( res.getvalue(0,6) ).to eq( {"b" => [2, 3]} )
|
442
|
-
end
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
it "should do array type conversions" do
|
447
|
-
[0].each do |format|
|
448
|
-
res = @conn.exec_params( "SELECT CAST('{1,2,3}' AS INT2[]), CAST('{{1,2},{3,4}}' AS INT2[][]),
|
449
|
-
CAST('{1,2,3}' AS INT4[]),
|
450
|
-
CAST('{1,2,3}' AS INT8[]),
|
451
|
-
CAST('{1,2,3}' AS TEXT[]),
|
452
|
-
CAST('{1,2,3}' AS VARCHAR[]),
|
453
|
-
CAST('{1,2,3}' AS FLOAT4[]),
|
454
|
-
CAST('{1,2,3}' AS FLOAT8[])
|
455
|
-
", [], format )
|
456
|
-
expect( res.getvalue(0,0) ).to eq( [1,2,3] )
|
457
|
-
expect( res.getvalue(0,1) ).to eq( [[1,2],[3,4]] )
|
458
|
-
expect( res.getvalue(0,2) ).to eq( [1,2,3] )
|
459
|
-
expect( res.getvalue(0,3) ).to eq( [1,2,3] )
|
460
|
-
expect( res.getvalue(0,4) ).to eq( ['1','2','3'] )
|
461
|
-
expect( res.getvalue(0,5) ).to eq( ['1','2','3'] )
|
462
|
-
expect( res.getvalue(0,6) ).to eq( [1.0,2.0,3.0] )
|
463
|
-
expect( res.getvalue(0,7) ).to eq( [1.0,2.0,3.0] )
|
464
|
-
end
|
465
|
-
end
|
466
|
-
|
467
|
-
it "should do inet type conversions" do
|
468
|
-
[0].each do |format|
|
469
|
-
vals = [
|
470
|
-
'1.2.3.4',
|
471
|
-
'0.0.0.0/0',
|
472
|
-
'1.0.0.0/8',
|
473
|
-
'1.2.0.0/16',
|
474
|
-
'1.2.3.0/24',
|
475
|
-
'1.2.3.4/24',
|
476
|
-
'1.2.3.4/32',
|
477
|
-
'1.2.3.128/25',
|
478
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012',
|
479
|
-
'::/0',
|
480
|
-
'1234:3456::/32',
|
481
|
-
'1234:3456:5678:789a::/64',
|
482
|
-
'1234:3456:5678:789a:9abc:bced::/96',
|
483
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012/128',
|
484
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012/0',
|
485
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012/32',
|
486
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012/64',
|
487
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012/96',
|
488
|
-
]
|
489
|
-
sql_vals = vals.map{|v| "CAST('#{v}' AS inet)"}
|
490
|
-
res = @conn.exec_params(("SELECT " + sql_vals.join(', ')), [], format )
|
491
|
-
vals.each_with_index do |v, i|
|
492
|
-
expect( res.getvalue(0,i) ).to eq( IPAddr.new(v) )
|
493
|
-
end
|
494
|
-
end
|
495
|
-
end
|
496
|
-
|
497
|
-
it "should do cidr type conversions" do
|
498
|
-
[0].each do |format|
|
499
|
-
vals = [
|
500
|
-
'0.0.0.0/0',
|
501
|
-
'1.0.0.0/8',
|
502
|
-
'1.2.0.0/16',
|
503
|
-
'1.2.3.0/24',
|
504
|
-
'1.2.3.4/32',
|
505
|
-
'1.2.3.128/25',
|
506
|
-
'::/0',
|
507
|
-
'1234:3456::/32',
|
508
|
-
'1234:3456:5678:789a::/64',
|
509
|
-
'1234:3456:5678:789a:9abc:bced::/96',
|
510
|
-
'1234:3456:5678:789a:9abc:bced:edf0:f012/128',
|
511
|
-
]
|
512
|
-
sql_vals = vals.map { |v| "CAST('#{v}' AS cidr)" }
|
513
|
-
res = @conn.exec_params(("SELECT " + sql_vals.join(', ')), [], format )
|
514
|
-
vals.each_with_index do |v, i|
|
515
|
-
val = res.getvalue(0,i)
|
516
|
-
ip, prefix = v.split('/', 2)
|
517
|
-
expect( val.to_s ).to eq( ip )
|
518
|
-
if val.respond_to?(:prefix)
|
519
|
-
val_prefix = val.prefix
|
520
|
-
else
|
521
|
-
default_prefix = (val.family == Socket::AF_INET ? 32 : 128)
|
522
|
-
range = val.to_range
|
523
|
-
val_prefix = default_prefix - Math.log(((range.end.to_i - range.begin.to_i) + 1), 2).to_i
|
524
|
-
end
|
525
|
-
if v.include?('/')
|
526
|
-
expect( val_prefix ).to eq( prefix.to_i )
|
527
|
-
elsif v.include?('.')
|
528
|
-
expect( val_prefix ).to eq( 32 )
|
529
|
-
else
|
530
|
-
expect( val_prefix ).to eq( 128 )
|
531
|
-
end
|
532
|
-
end
|
533
|
-
end
|
534
|
-
end
|
535
|
-
end
|
536
|
-
|
537
|
-
context "with usage of result oids for copy decoder selection" do
|
538
|
-
it "can type cast #copy_data output with explicit decoder" do
|
539
|
-
@conn.exec( "CREATE TEMP TABLE copytable (t TEXT, i INT, ai INT[])" )
|
540
|
-
@conn.exec( "INSERT INTO copytable VALUES ('a', 123, '{5,4,3}'), ('b', 234, '{2,3}')" )
|
541
|
-
|
542
|
-
# Retrieve table OIDs per empty result.
|
543
|
-
res = @conn.exec( "SELECT * FROM copytable LIMIT 0" )
|
544
|
-
tm = basic_type_mapping.build_column_map( res )
|
545
|
-
row_decoder = PG::TextDecoder::CopyRow.new type_map: tm
|
546
|
-
|
547
|
-
rows = []
|
548
|
-
@conn.copy_data( "COPY copytable TO STDOUT", row_decoder ) do |res|
|
549
|
-
while row=@conn.get_copy_data
|
550
|
-
rows << row
|
551
|
-
end
|
552
|
-
end
|
553
|
-
expect( rows ).to eq( [['a', 123, [5,4,3]], ['b', 234, [2,3]]] )
|
554
|
-
end
|
555
|
-
end
|
556
|
-
end
|
557
|
-
|
558
|
-
|
559
|
-
describe PG::BasicTypeMapBasedOnResult do
|
560
|
-
let!(:basic_type_mapping) do
|
561
|
-
PG::BasicTypeMapBasedOnResult.new @conn
|
562
|
-
end
|
563
|
-
|
564
|
-
context "with usage of result oids for bind params encoder selection" do
|
565
|
-
it "can type cast query params" do
|
566
|
-
@conn.exec( "CREATE TEMP TABLE copytable (t TEXT, i INT, ai INT[])" )
|
567
|
-
|
568
|
-
# Retrieve table OIDs per empty result.
|
569
|
-
res = @conn.exec( "SELECT * FROM copytable LIMIT 0" )
|
570
|
-
tm = basic_type_mapping.build_column_map( res )
|
571
|
-
|
572
|
-
@conn.exec_params( "INSERT INTO copytable VALUES ($1, $2, $3)", ['a', 123, [5,4,3]], 0, tm )
|
573
|
-
@conn.exec_params( "INSERT INTO copytable VALUES ($1, $2, $3)", ['b', 234, [2,3]], 0, tm )
|
574
|
-
res = @conn.exec( "SELECT * FROM copytable" )
|
575
|
-
expect( res.values ).to eq( [['a', '123', '{5,4,3}'], ['b', '234', '{2,3}']] )
|
576
|
-
end
|
577
|
-
|
578
|
-
it "can do JSON conversions", :postgresql_94 do
|
579
|
-
['JSON', 'JSONB'].each do |type|
|
580
|
-
sql = "SELECT CAST('123' AS #{type}),
|
581
|
-
CAST('12.3' AS #{type}),
|
582
|
-
CAST('true' AS #{type}),
|
583
|
-
CAST('false' AS #{type}),
|
584
|
-
CAST('null' AS #{type}),
|
585
|
-
CAST('[1, \"a\", null]' AS #{type}),
|
586
|
-
CAST('{\"b\" : [2,3]}' AS #{type})"
|
587
|
-
|
588
|
-
tm = basic_type_mapping.build_column_map( @conn.exec( sql ) )
|
589
|
-
expect( tm.coders.map(&:name) ).to eq( [type.downcase] * 7 )
|
590
|
-
|
591
|
-
res = @conn.exec_params( "SELECT $1, $2, $3, $4, $5, $6, $7",
|
592
|
-
[ 123,
|
593
|
-
12.3,
|
594
|
-
true,
|
595
|
-
false,
|
596
|
-
nil,
|
597
|
-
[1, "a", nil],
|
598
|
-
{"b" => [2, 3]},
|
599
|
-
], 0, tm )
|
600
|
-
|
601
|
-
expect( res.getvalue(0,0) ).to eq( "123" )
|
602
|
-
expect( res.getvalue(0,1) ).to eq( "12.3" )
|
603
|
-
expect( res.getvalue(0,2) ).to eq( "true" )
|
604
|
-
expect( res.getvalue(0,3) ).to eq( "false" )
|
605
|
-
expect( res.getvalue(0,4) ).to eq( nil )
|
606
|
-
expect( res.getvalue(0,5).gsub(" ","") ).to eq( "[1,\"a\",null]" )
|
607
|
-
expect( res.getvalue(0,6).gsub(" ","") ).to eq( "{\"b\":[2,3]}" )
|
608
|
-
end
|
609
|
-
end
|
610
|
-
end
|
611
|
-
|
612
|
-
context "with usage of result oids for copy encoder selection" do
|
613
|
-
it "can type cast #copy_data input with explicit encoder" do
|
614
|
-
@conn.exec( "CREATE TEMP TABLE copytable (t TEXT, i INT, ai INT[])" )
|
615
|
-
|
616
|
-
# Retrieve table OIDs per empty result set.
|
617
|
-
res = @conn.exec( "SELECT * FROM copytable LIMIT 0" )
|
618
|
-
tm = basic_type_mapping.build_column_map( res )
|
619
|
-
row_encoder = PG::TextEncoder::CopyRow.new type_map: tm
|
620
|
-
|
621
|
-
@conn.copy_data( "COPY copytable FROM STDIN", row_encoder ) do |res|
|
622
|
-
@conn.put_copy_data ['a', 123, [5,4,3]]
|
623
|
-
@conn.put_copy_data ['b', 234, [2,3]]
|
624
|
-
end
|
625
|
-
res = @conn.exec( "SELECT * FROM copytable" )
|
626
|
-
expect( res.values ).to eq( [['a', '123', '{5,4,3}'], ['b', '234', '{2,3}']] )
|
627
|
-
end
|
628
|
-
end
|
629
|
-
end
|
630
|
-
end
|