pg 0.18.0 → 1.1.4
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 +200 -0
- data/Manifest.txt +5 -18
- data/README-Windows.rdoc +15 -26
- data/README.rdoc +27 -10
- data/Rakefile +33 -24
- data/Rakefile.cross +57 -39
- data/ext/errorcodes.def +37 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +16 -1
- data/ext/extconf.rb +29 -35
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +27 -39
- data/ext/pg.c +27 -53
- data/ext/pg.h +66 -83
- data/ext/pg_binary_decoder.c +75 -6
- data/ext/pg_binary_encoder.c +14 -12
- data/ext/pg_coder.c +83 -13
- data/ext/pg_connection.c +627 -351
- data/ext/pg_copy_coder.c +44 -9
- data/ext/pg_result.c +364 -134
- data/ext/pg_text_decoder.c +605 -46
- data/ext/pg_text_encoder.c +95 -76
- data/ext/pg_tuple.c +541 -0
- 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 +7 -7
- data/ext/util.h +3 -3
- data/lib/pg/basic_type_mapping.rb +105 -45
- data/lib/pg/binary_decoder.rb +22 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +109 -39
- data/lib/pg/constants.rb +1 -1
- data/lib/pg/exceptions.rb +1 -1
- data/lib/pg/result.rb +11 -6
- data/lib/pg/text_decoder.rb +25 -20
- data/lib/pg/text_encoder.rb +43 -1
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +1 -1
- data/lib/pg.rb +21 -11
- data/spec/helpers.rb +50 -25
- data/spec/pg/basic_type_mapping_spec.rb +287 -30
- data/spec/pg/connection_spec.rb +695 -282
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +59 -17
- data/spec/pg/tuple_spec.rb +280 -0
- data/spec/pg/type_map_by_class_spec.rb +3 -3
- data/spec/pg/type_map_by_column_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +2 -2
- data/spec/pg/type_map_by_oid_spec.rb +1 -1
- data/spec/pg/type_map_in_ruby_spec.rb +1 -1
- data/spec/pg/type_map_spec.rb +1 -1
- data/spec/pg/type_spec.rb +319 -35
- data/spec/pg_spec.rb +2 -2
- data.tar.gz.sig +0 -0
- metadata +68 -68
- 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
@@ -1,9 +1,25 @@
|
|
1
|
-
|
1
|
+
# -*- rspec -*-
|
2
2
|
# encoding: utf-8
|
3
3
|
|
4
4
|
require_relative '../helpers'
|
5
5
|
|
6
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
|
7
23
|
|
8
24
|
describe 'Basic type mapping' do
|
9
25
|
|
@@ -42,6 +58,30 @@ describe 'Basic type mapping' do
|
|
42
58
|
|
43
59
|
expect( result_typenames(res) ).to eq( ['bigint[]', 'bigint[]', 'double precision[]', 'text[]'] )
|
44
60
|
end
|
61
|
+
|
62
|
+
it "should do bigdecimal param encoding" do
|
63
|
+
large = ('123456790'*10) << '.' << ('012345679')
|
64
|
+
res = @conn.exec_params( "SELECT $1::numeric,$2::numeric",
|
65
|
+
[BigDecimal('1'), BigDecimal(large)], nil, basic_type_mapping )
|
66
|
+
|
67
|
+
expect( res.values ).to eq( [
|
68
|
+
[ "1.0", large ],
|
69
|
+
] )
|
70
|
+
|
71
|
+
expect( result_typenames(res) ).to eq( ['numeric', 'numeric'] )
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should do IPAddr param encoding" do
|
75
|
+
res = @conn.exec_params( "SELECT $1::inet,$2::inet,$3::cidr,$4::cidr",
|
76
|
+
['1.2.3.4', IPAddr.new('1234::5678'), '1.2.3.4', IPAddr.new('1234:5678::/32')], nil, basic_type_mapping )
|
77
|
+
|
78
|
+
expect( res.values ).to eq( [
|
79
|
+
[ '1.2.3.4', '1234::5678', '1.2.3.4/32', '1234:5678::/32'],
|
80
|
+
] )
|
81
|
+
|
82
|
+
expect( result_typenames(res) ).to eq( ['inet', 'inet', 'cidr', 'cidr'] )
|
83
|
+
end
|
84
|
+
|
45
85
|
end
|
46
86
|
|
47
87
|
|
@@ -58,8 +98,8 @@ describe 'Basic type mapping' do
|
|
58
98
|
it "should do OID based type conversions", :ruby_19 do
|
59
99
|
res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, TRUE, '2013-06-30'::DATE, generate_series(4,5)" )
|
60
100
|
expect( res.map_types!(basic_type_mapping).values ).to eq( [
|
61
|
-
[ 1, 'a', 2.0, true,
|
62
|
-
[ 1, 'a', 2.0, true,
|
101
|
+
[ 1, 'a', 2.0, true, Date.new(2013,6,30), 4 ],
|
102
|
+
[ 1, 'a', 2.0, true, Date.new(2013,6,30), 5 ],
|
63
103
|
] )
|
64
104
|
end
|
65
105
|
|
@@ -78,14 +118,14 @@ describe 'Basic type mapping' do
|
|
78
118
|
|
79
119
|
it "should do boolean type conversions" do
|
80
120
|
[1, 0].each do |format|
|
81
|
-
res = @conn.
|
121
|
+
res = @conn.exec_params( "SELECT true::BOOLEAN, false::BOOLEAN, NULL::BOOLEAN", [], format )
|
82
122
|
expect( res.values ).to eq( [[true, false, nil]] )
|
83
123
|
end
|
84
124
|
end
|
85
125
|
|
86
126
|
it "should do binary type conversions" do
|
87
127
|
[1, 0].each do |format|
|
88
|
-
res = @conn.
|
128
|
+
res = @conn.exec_params( "SELECT E'\\\\000\\\\377'::BYTEA", [], format )
|
89
129
|
expect( res.values ).to eq( [[["00ff"].pack("H*")]] )
|
90
130
|
expect( res.values[0][0].encoding ).to eq( Encoding::ASCII_8BIT ) if Object.const_defined? :Encoding
|
91
131
|
end
|
@@ -93,7 +133,7 @@ describe 'Basic type mapping' do
|
|
93
133
|
|
94
134
|
it "should do integer type conversions" do
|
95
135
|
[1, 0].each do |format|
|
96
|
-
res = @conn.
|
136
|
+
res = @conn.exec_params( "SELECT -8999::INT2, -899999999::INT4, -8999999999999999999::INT8", [], format )
|
97
137
|
expect( res.values ).to eq( [[-8999, -899999999, -8999999999999999999]] )
|
98
138
|
end
|
99
139
|
end
|
@@ -101,7 +141,7 @@ describe 'Basic type mapping' do
|
|
101
141
|
it "should do string type conversions" do
|
102
142
|
@conn.internal_encoding = 'utf-8' if Object.const_defined? :Encoding
|
103
143
|
[1, 0].each do |format|
|
104
|
-
res = @conn.
|
144
|
+
res = @conn.exec_params( "SELECT 'abcäöü'::TEXT", [], format )
|
105
145
|
expect( res.values ).to eq( [['abcäöü']] )
|
106
146
|
expect( res.values[0][0].encoding ).to eq( Encoding::UTF_8 ) if Object.const_defined? :Encoding
|
107
147
|
end
|
@@ -109,7 +149,7 @@ describe 'Basic type mapping' do
|
|
109
149
|
|
110
150
|
it "should do float type conversions" do
|
111
151
|
[1, 0].each do |format|
|
112
|
-
res = @conn.
|
152
|
+
res = @conn.exec_params( "SELECT -8.999e3::FLOAT4,
|
113
153
|
8.999e10::FLOAT4,
|
114
154
|
-8999999999e-99::FLOAT8,
|
115
155
|
NULL::FLOAT4,
|
@@ -127,48 +167,162 @@ describe 'Basic type mapping' do
|
|
127
167
|
end
|
128
168
|
end
|
129
169
|
|
130
|
-
it "should do datetime without time zone type conversions" do
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
170
|
+
it "should do text datetime without time zone type conversions" do
|
171
|
+
# for backward compat text timestamps without time zone are treated as local times
|
172
|
+
res = @conn.exec_params( "SELECT CAST('2013-12-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
173
|
+
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
174
|
+
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
175
|
+
CAST('294276-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
176
|
+
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
177
|
+
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], 0 )
|
178
|
+
expect( res.getvalue(0,0) ).to eq( Time.new(2013, 12, 31, 23, 58, 59) )
|
179
|
+
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.new(1913, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
180
|
+
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.new(-4713, 11, 24, 23, 58, 59.1231).iso8601(3) )
|
181
|
+
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.new(294276, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
182
|
+
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
183
|
+
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
184
|
+
end
|
185
|
+
|
186
|
+
[1, 0].each do |format|
|
187
|
+
it "should convert format #{format} timestamps per TimestampUtc" do
|
188
|
+
restore_type("timestamp") do
|
189
|
+
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampUtc
|
190
|
+
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
191
|
+
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
192
|
+
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
193
|
+
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
194
|
+
CAST('294276-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
195
|
+
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
196
|
+
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
|
197
|
+
expect( res.getvalue(0,0).iso8601(3) ).to eq( Time.utc(2013, 7, 31, 23, 58, 59).iso8601(3) )
|
198
|
+
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.utc(1913, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
199
|
+
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.utc(-4713, 11, 24, 23, 58, 59.1231).iso8601(3) )
|
200
|
+
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.utc(294276, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
201
|
+
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
202
|
+
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
203
|
+
end
|
140
204
|
end
|
141
205
|
end
|
142
206
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
207
|
+
[1, 0].each do |format|
|
208
|
+
it "should convert format #{format} timestamps per TimestampUtcToLocal" do
|
209
|
+
restore_type("timestamp") do
|
210
|
+
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampUtcToLocal
|
211
|
+
PG::BasicTypeRegistry.register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampUtcToLocal
|
212
|
+
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
213
|
+
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
214
|
+
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
215
|
+
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
216
|
+
CAST('294276-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
217
|
+
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
218
|
+
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
|
219
|
+
expect( res.getvalue(0,0).iso8601(3) ).to eq( Time.utc(2013, 7, 31, 23, 58, 59).getlocal.iso8601(3) )
|
220
|
+
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.utc(1913, 12, 31, 23, 58, 59.1231).getlocal.iso8601(3) )
|
221
|
+
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.utc(-4713, 11, 24, 23, 58, 59.1231).getlocal.iso8601(3) )
|
222
|
+
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.utc(294276, 12, 31, 23, 58, 59.1231).getlocal.iso8601(3) )
|
223
|
+
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
224
|
+
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
[1, 0].each do |format|
|
230
|
+
it "should convert format #{format} timestamps per TimestampLocal" do
|
231
|
+
restore_type("timestamp") do
|
232
|
+
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampLocal
|
233
|
+
PG::BasicTypeRegistry.register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampLocal
|
234
|
+
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
235
|
+
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59' AS TIMESTAMP WITHOUT TIME ZONE),
|
236
|
+
CAST('1913-12-31 23:58:59.1231' AS TIMESTAMP WITHOUT TIME ZONE),
|
237
|
+
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
238
|
+
CAST('294276-12-31 23:58:59.1231+03' AS TIMESTAMP WITHOUT TIME ZONE),
|
239
|
+
CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
|
240
|
+
CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
|
241
|
+
expect( res.getvalue(0,0).iso8601(3) ).to eq( Time.new(2013, 7, 31, 23, 58, 59).iso8601(3) )
|
242
|
+
expect( res.getvalue(0,1).iso8601(3) ).to eq( Time.new(1913, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
243
|
+
expect( res.getvalue(0,2).iso8601(3) ).to eq( Time.new(-4713, 11, 24, 23, 58, 59.1231).iso8601(3) )
|
244
|
+
expect( res.getvalue(0,3).iso8601(3) ).to eq( Time.new(294276, 12, 31, 23, 58, 59.1231).iso8601(3) )
|
245
|
+
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
246
|
+
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
[0, 1].each do |format|
|
252
|
+
it "should convert format #{format} timestamps with time zone" do
|
253
|
+
res = @conn.exec_params( "SELECT CAST('2013-12-31 23:58:59+02' AS TIMESTAMP WITH TIME ZONE),
|
254
|
+
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITH TIME ZONE),
|
255
|
+
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITH TIME ZONE),
|
256
|
+
CAST('294276-12-31 23:58:59.1231+03' AS TIMESTAMP WITH TIME ZONE),
|
147
257
|
CAST('infinity' AS TIMESTAMP WITH TIME ZONE),
|
148
258
|
CAST('-infinity' AS TIMESTAMP WITH TIME ZONE)", [], format )
|
149
|
-
expect( res.getvalue(0,0) ).to
|
150
|
-
expect( res.getvalue(0,1) ).to be_within(1e-3).of(Time.new(1913, 12, 31, 23, 58, 59.
|
151
|
-
expect( res.getvalue(0,2) ).to
|
152
|
-
expect( res.getvalue(0,3) ).to
|
259
|
+
expect( res.getvalue(0,0) ).to be_within(1e-3).of( Time.new(2013, 12, 31, 23, 58, 59, "+02:00").getlocal )
|
260
|
+
expect( res.getvalue(0,1) ).to be_within(1e-3).of( Time.new(1913, 12, 31, 23, 58, 59.1231, "-03:00").getlocal )
|
261
|
+
expect( res.getvalue(0,2) ).to be_within(1e-3).of( Time.new(-4713, 11, 24, 23, 58, 59.1231, "-03:00").getlocal )
|
262
|
+
expect( res.getvalue(0,3) ).to be_within(1e-3).of( Time.new(294276, 12, 31, 23, 58, 59.1231, "+03:00").getlocal )
|
263
|
+
expect( res.getvalue(0,4) ).to eq( 'infinity' )
|
264
|
+
expect( res.getvalue(0,5) ).to eq( '-infinity' )
|
153
265
|
end
|
154
266
|
end
|
155
267
|
|
156
268
|
it "should do date type conversions" do
|
157
269
|
[0].each do |format|
|
158
|
-
res = @conn.
|
270
|
+
res = @conn.exec_params( "SELECT CAST('2113-12-31' AS DATE),
|
159
271
|
CAST('1913-12-31' AS DATE),
|
160
272
|
CAST('infinity' AS DATE),
|
161
273
|
CAST('-infinity' AS DATE)", [], format )
|
162
|
-
expect( res.getvalue(0,0) ).to eq(
|
163
|
-
expect( res.getvalue(0,1) ).to eq(
|
274
|
+
expect( res.getvalue(0,0) ).to eq( Date.new(2113, 12, 31) )
|
275
|
+
expect( res.getvalue(0,1) ).to eq( Date.new(1913, 12, 31) )
|
164
276
|
expect( res.getvalue(0,2) ).to eq( 'infinity' )
|
165
277
|
expect( res.getvalue(0,3) ).to eq( '-infinity' )
|
166
278
|
end
|
167
279
|
end
|
168
280
|
|
281
|
+
it "should do numeric type conversions" do
|
282
|
+
[0].each do |format|
|
283
|
+
small = '123456790123.12'
|
284
|
+
large = ('123456790'*10) << '.' << ('012345679')
|
285
|
+
numerics = [
|
286
|
+
'1',
|
287
|
+
'1.0',
|
288
|
+
'1.2',
|
289
|
+
small,
|
290
|
+
large,
|
291
|
+
]
|
292
|
+
sql_numerics = numerics.map { |v| "CAST(#{v} AS numeric)" }
|
293
|
+
res = @conn.exec_params( "SELECT #{sql_numerics.join(',')}", [], format )
|
294
|
+
expect( res.getvalue(0,0) ).to eq( BigDecimal('1') )
|
295
|
+
expect( res.getvalue(0,1) ).to eq( BigDecimal('1') )
|
296
|
+
expect( res.getvalue(0,2) ).to eq( BigDecimal('1.2') )
|
297
|
+
expect( res.getvalue(0,3) ).to eq( BigDecimal(small) )
|
298
|
+
expect( res.getvalue(0,4) ).to eq( BigDecimal(large) )
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should do JSON conversions", :postgresql_94 do
|
303
|
+
[0].each do |format|
|
304
|
+
['JSON', 'JSONB'].each do |type|
|
305
|
+
res = @conn.exec_params( "SELECT CAST('123' AS #{type}),
|
306
|
+
CAST('12.3' AS #{type}),
|
307
|
+
CAST('true' AS #{type}),
|
308
|
+
CAST('false' AS #{type}),
|
309
|
+
CAST('null' AS #{type}),
|
310
|
+
CAST('[1, \"a\", null]' AS #{type}),
|
311
|
+
CAST('{\"b\" : [2,3]}' AS #{type})", [], format )
|
312
|
+
expect( res.getvalue(0,0) ).to eq( 123 )
|
313
|
+
expect( res.getvalue(0,1) ).to be_within(0.1).of( 12.3 )
|
314
|
+
expect( res.getvalue(0,2) ).to eq( true )
|
315
|
+
expect( res.getvalue(0,3) ).to eq( false )
|
316
|
+
expect( res.getvalue(0,4) ).to eq( nil )
|
317
|
+
expect( res.getvalue(0,5) ).to eq( [1, "a", nil] )
|
318
|
+
expect( res.getvalue(0,6) ).to eq( {"b" => [2, 3]} )
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
169
323
|
it "should do array type conversions" do
|
170
324
|
[0].each do |format|
|
171
|
-
res = @conn.
|
325
|
+
res = @conn.exec_params( "SELECT CAST('{1,2,3}' AS INT2[]), CAST('{{1,2},{3,4}}' AS INT2[][]),
|
172
326
|
CAST('{1,2,3}' AS INT4[]),
|
173
327
|
CAST('{1,2,3}' AS INT8[]),
|
174
328
|
CAST('{1,2,3}' AS TEXT[]),
|
@@ -186,6 +340,76 @@ describe 'Basic type mapping' do
|
|
186
340
|
expect( res.getvalue(0,7) ).to eq( [1.0,2.0,3.0] )
|
187
341
|
end
|
188
342
|
end
|
343
|
+
|
344
|
+
it "should do inet type conversions" do
|
345
|
+
[0].each do |format|
|
346
|
+
vals = [
|
347
|
+
'1.2.3.4',
|
348
|
+
'0.0.0.0/0',
|
349
|
+
'1.0.0.0/8',
|
350
|
+
'1.2.0.0/16',
|
351
|
+
'1.2.3.0/24',
|
352
|
+
'1.2.3.4/24',
|
353
|
+
'1.2.3.4/32',
|
354
|
+
'1.2.3.128/25',
|
355
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012',
|
356
|
+
'::/0',
|
357
|
+
'1234:3456::/32',
|
358
|
+
'1234:3456:5678:789a::/64',
|
359
|
+
'1234:3456:5678:789a:9abc:bced::/96',
|
360
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012/128',
|
361
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012/0',
|
362
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012/32',
|
363
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012/64',
|
364
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012/96',
|
365
|
+
]
|
366
|
+
sql_vals = vals.map{|v| "CAST('#{v}' AS inet)"}
|
367
|
+
res = @conn.exec_params(("SELECT " + sql_vals.join(', ')), [], format )
|
368
|
+
vals.each_with_index do |v, i|
|
369
|
+
val = res.getvalue(0,i)
|
370
|
+
expect( res.getvalue(0,i) ).to eq( IPAddr.new(v) )
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
it "should do cidr type conversions" do
|
376
|
+
[0].each do |format|
|
377
|
+
vals = [
|
378
|
+
'0.0.0.0/0',
|
379
|
+
'1.0.0.0/8',
|
380
|
+
'1.2.0.0/16',
|
381
|
+
'1.2.3.0/24',
|
382
|
+
'1.2.3.4/32',
|
383
|
+
'1.2.3.128/25',
|
384
|
+
'::/0',
|
385
|
+
'1234:3456::/32',
|
386
|
+
'1234:3456:5678:789a::/64',
|
387
|
+
'1234:3456:5678:789a:9abc:bced::/96',
|
388
|
+
'1234:3456:5678:789a:9abc:bced:edf0:f012/128',
|
389
|
+
]
|
390
|
+
sql_vals = vals.map { |v| "CAST('#{v}' AS cidr)" }
|
391
|
+
res = @conn.exec_params(("SELECT " + sql_vals.join(', ')), [], format )
|
392
|
+
vals.each_with_index do |v, i|
|
393
|
+
val = res.getvalue(0,i)
|
394
|
+
ip, prefix = v.split('/', 2)
|
395
|
+
expect( val.to_s ).to eq( ip )
|
396
|
+
if val.respond_to?(:prefix)
|
397
|
+
val_prefix = val.prefix
|
398
|
+
else
|
399
|
+
default_prefix = (val.family == Socket::AF_INET ? 32 : 128)
|
400
|
+
range = val.to_range
|
401
|
+
val_prefix = default_prefix - Math.log(((range.end.to_i - range.begin.to_i) + 1), 2).to_i
|
402
|
+
end
|
403
|
+
if v.include?('/')
|
404
|
+
expect( val_prefix ).to eq( prefix.to_i )
|
405
|
+
elsif v.include?('.')
|
406
|
+
expect( val_prefix ).to eq( 32 )
|
407
|
+
else
|
408
|
+
expect( val_prefix ).to eq( 128 )
|
409
|
+
end
|
410
|
+
end
|
411
|
+
end
|
412
|
+
end
|
189
413
|
end
|
190
414
|
|
191
415
|
context "with usage of result oids for copy decoder selection" do
|
@@ -228,6 +452,39 @@ describe 'Basic type mapping' do
|
|
228
452
|
res = @conn.exec( "SELECT * FROM copytable" )
|
229
453
|
expect( res.values ).to eq( [['a', '123', '{5,4,3}'], ['b', '234', '{2,3}']] )
|
230
454
|
end
|
455
|
+
|
456
|
+
it "can do JSON conversions", :postgresql_94 do
|
457
|
+
['JSON', 'JSONB'].each do |type|
|
458
|
+
sql = "SELECT CAST('123' AS #{type}),
|
459
|
+
CAST('12.3' AS #{type}),
|
460
|
+
CAST('true' AS #{type}),
|
461
|
+
CAST('false' AS #{type}),
|
462
|
+
CAST('null' AS #{type}),
|
463
|
+
CAST('[1, \"a\", null]' AS #{type}),
|
464
|
+
CAST('{\"b\" : [2,3]}' AS #{type})"
|
465
|
+
|
466
|
+
tm = basic_type_mapping.build_column_map( @conn.exec( sql ) )
|
467
|
+
expect( tm.coders.map(&:name) ).to eq( [type.downcase] * 7 )
|
468
|
+
|
469
|
+
res = @conn.exec_params( "SELECT $1, $2, $3, $4, $5, $6, $7",
|
470
|
+
[ 123,
|
471
|
+
12.3,
|
472
|
+
true,
|
473
|
+
false,
|
474
|
+
nil,
|
475
|
+
[1, "a", nil],
|
476
|
+
{"b" => [2, 3]},
|
477
|
+
], 0, tm )
|
478
|
+
|
479
|
+
expect( res.getvalue(0,0) ).to eq( "123" )
|
480
|
+
expect( res.getvalue(0,1) ).to eq( "12.3" )
|
481
|
+
expect( res.getvalue(0,2) ).to eq( "true" )
|
482
|
+
expect( res.getvalue(0,3) ).to eq( "false" )
|
483
|
+
expect( res.getvalue(0,4) ).to eq( nil )
|
484
|
+
expect( res.getvalue(0,5).gsub(" ","") ).to eq( "[1,\"a\",null]" )
|
485
|
+
expect( res.getvalue(0,6).gsub(" ","") ).to eq( "{\"b\":[2,3]}" )
|
486
|
+
end
|
487
|
+
end
|
231
488
|
end
|
232
489
|
|
233
490
|
context "with usage of result oids for copy encoder selection" do
|