pg 0.19.0 → 1.1.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.
Files changed (74) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/ChangeLog +218 -1
  4. data/History.rdoc +106 -0
  5. data/Manifest.txt +5 -18
  6. data/README.rdoc +15 -5
  7. data/Rakefile +8 -9
  8. data/Rakefile.cross +19 -22
  9. data/ext/errorcodes.def +17 -0
  10. data/ext/errorcodes.rb +1 -1
  11. data/ext/errorcodes.txt +11 -1
  12. data/ext/extconf.rb +14 -32
  13. data/ext/gvl_wrappers.c +4 -0
  14. data/ext/gvl_wrappers.h +23 -39
  15. data/ext/pg.c +19 -48
  16. data/ext/pg.h +46 -81
  17. data/ext/pg_binary_decoder.c +69 -6
  18. data/ext/pg_coder.c +53 -4
  19. data/ext/pg_connection.c +401 -253
  20. data/ext/pg_copy_coder.c +10 -5
  21. data/ext/pg_result.c +359 -131
  22. data/ext/pg_text_decoder.c +597 -37
  23. data/ext/pg_text_encoder.c +6 -7
  24. data/ext/pg_tuple.c +541 -0
  25. data/ext/pg_type_map.c +14 -7
  26. data/ext/util.c +6 -6
  27. data/ext/util.h +2 -2
  28. data/lib/pg/basic_type_mapping.rb +40 -7
  29. data/lib/pg/binary_decoder.rb +22 -0
  30. data/lib/pg/coder.rb +1 -1
  31. data/lib/pg/connection.rb +27 -7
  32. data/lib/pg/constants.rb +1 -1
  33. data/lib/pg/exceptions.rb +1 -1
  34. data/lib/pg/result.rb +6 -5
  35. data/lib/pg/text_decoder.rb +19 -23
  36. data/lib/pg/text_encoder.rb +36 -2
  37. data/lib/pg/tuple.rb +30 -0
  38. data/lib/pg/type_map_by_column.rb +1 -1
  39. data/lib/pg.rb +21 -11
  40. data/spec/helpers.rb +47 -19
  41. data/spec/pg/basic_type_mapping_spec.rb +230 -27
  42. data/spec/pg/connection_spec.rb +402 -275
  43. data/spec/pg/connection_sync_spec.rb +41 -0
  44. data/spec/pg/result_spec.rb +59 -17
  45. data/spec/pg/tuple_spec.rb +280 -0
  46. data/spec/pg/type_map_by_class_spec.rb +2 -2
  47. data/spec/pg/type_map_by_column_spec.rb +1 -1
  48. data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
  49. data/spec/pg/type_map_by_oid_spec.rb +1 -1
  50. data/spec/pg/type_map_in_ruby_spec.rb +1 -1
  51. data/spec/pg/type_map_spec.rb +1 -1
  52. data/spec/pg/type_spec.rb +184 -12
  53. data/spec/pg_spec.rb +2 -2
  54. data.tar.gz.sig +0 -0
  55. metadata +47 -53
  56. metadata.gz.sig +0 -0
  57. data/sample/array_insert.rb +0 -20
  58. data/sample/async_api.rb +0 -106
  59. data/sample/async_copyto.rb +0 -39
  60. data/sample/async_mixed.rb +0 -56
  61. data/sample/check_conn.rb +0 -21
  62. data/sample/copyfrom.rb +0 -81
  63. data/sample/copyto.rb +0 -19
  64. data/sample/cursor.rb +0 -21
  65. data/sample/disk_usage_report.rb +0 -186
  66. data/sample/issue-119.rb +0 -94
  67. data/sample/losample.rb +0 -69
  68. data/sample/minimal-testcase.rb +0 -17
  69. data/sample/notify_wait.rb +0 -72
  70. data/sample/pg_statistics.rb +0 -294
  71. data/sample/replication_monitor.rb +0 -231
  72. data/sample/test_binary_values.rb +0 -33
  73. data/sample/wal_shipper.rb +0 -434
  74. data/sample/warehouse_partitions.rb +0 -320
@@ -1,9 +1,25 @@
1
- #!/usr/bin/env rspec
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.new('1'), BigDecimal.new(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
 
@@ -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.exec( "SELECT true::BOOLEAN, false::BOOLEAN, NULL::BOOLEAN", [], format )
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.exec( "SELECT E'\\\\000\\\\377'::BYTEA", [], format )
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.exec( "SELECT -8999::INT2, -899999999::INT4, -8999999999999999999::INT8", [], format )
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.exec( "SELECT 'abcäöü'::TEXT", [], format )
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.exec( "SELECT -8.999e3::FLOAT4,
152
+ res = @conn.exec_params( "SELECT -8.999e3::FLOAT4,
113
153
  8.999e10::FLOAT4,
114
154
  -8999999999e-99::FLOAT8,
115
155
  NULL::FLOAT4,
@@ -127,35 +167,107 @@ 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
- [0].each do |format|
132
- res = @conn.exec( "SELECT CAST('2013-12-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
133
- CAST('1913-12-31 23:58:59.123-03' AS TIMESTAMP WITHOUT TIME ZONE),
134
- CAST('infinity' AS TIMESTAMP WITHOUT TIME ZONE),
135
- CAST('-infinity' AS TIMESTAMP WITHOUT TIME ZONE)", [], format )
136
- expect( res.getvalue(0,0) ).to eq( Time.new(2013, 12, 31, 23, 58, 59) )
137
- expect( res.getvalue(0,1) ).to be_within(1e-3).of(Time.new(1913, 12, 31, 23, 58, 59.123))
138
- expect( res.getvalue(0,2) ).to eq( 'infinity' )
139
- expect( res.getvalue(0,3) ).to eq( '-infinity' )
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
- it "should do datetime with time zone type conversions" do
144
- [0].each do |format|
145
- res = @conn.exec( "SELECT CAST('2013-12-31 23:58:59+02' AS TIMESTAMP WITH TIME ZONE),
146
- CAST('1913-12-31 23:58:59.123-03' AS TIMESTAMP WITH TIME ZONE),
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 eq( Time.new(2013, 12, 31, 23, 58, 59, "+02:00") )
150
- expect( res.getvalue(0,1) ).to be_within(1e-3).of(Time.new(1913, 12, 31, 23, 58, 59.123, "-03:00"))
151
- expect( res.getvalue(0,2) ).to eq( 'infinity' )
152
- expect( res.getvalue(0,3) ).to eq( '-infinity' )
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.exec( "SELECT CAST('2113-12-31' AS DATE),
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 )
@@ -166,10 +278,31 @@ describe 'Basic type mapping' do
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
+
169
302
  it "should do JSON conversions", :postgresql_94 do
170
303
  [0].each do |format|
171
304
  ['JSON', 'JSONB'].each do |type|
172
- res = @conn.exec( "SELECT CAST('123' AS #{type}),
305
+ res = @conn.exec_params( "SELECT CAST('123' AS #{type}),
173
306
  CAST('12.3' AS #{type}),
174
307
  CAST('true' AS #{type}),
175
308
  CAST('false' AS #{type}),
@@ -189,7 +322,7 @@ describe 'Basic type mapping' do
189
322
 
190
323
  it "should do array type conversions" do
191
324
  [0].each do |format|
192
- res = @conn.exec( "SELECT CAST('{1,2,3}' AS INT2[]), CAST('{{1,2},{3,4}}' AS INT2[][]),
325
+ res = @conn.exec_params( "SELECT CAST('{1,2,3}' AS INT2[]), CAST('{{1,2},{3,4}}' AS INT2[][]),
193
326
  CAST('{1,2,3}' AS INT4[]),
194
327
  CAST('{1,2,3}' AS INT8[]),
195
328
  CAST('{1,2,3}' AS TEXT[]),
@@ -207,6 +340,76 @@ describe 'Basic type mapping' do
207
340
  expect( res.getvalue(0,7) ).to eq( [1.0,2.0,3.0] )
208
341
  end
209
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
210
413
  end
211
414
 
212
415
  context "with usage of result oids for copy decoder selection" do