pg 0.21.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.tar.gz.sig +0 -0
- data/History.rdoc +98 -0
- data/Manifest.txt +5 -1
- data/README.rdoc +14 -4
- data/Rakefile +4 -5
- data/Rakefile.cross +17 -21
- data/ext/errorcodes.def +12 -0
- data/ext/errorcodes.rb +1 -1
- data/ext/errorcodes.txt +4 -1
- data/ext/extconf.rb +14 -32
- data/ext/gvl_wrappers.c +4 -0
- data/ext/gvl_wrappers.h +23 -39
- data/ext/pg.c +23 -50
- data/ext/pg.h +51 -81
- data/ext/pg_binary_decoder.c +73 -6
- data/ext/pg_coder.c +52 -3
- data/ext/pg_connection.c +369 -219
- data/ext/pg_copy_coder.c +10 -5
- data/ext/pg_result.c +343 -119
- data/ext/pg_text_decoder.c +597 -37
- data/ext/pg_text_encoder.c +6 -7
- data/ext/pg_tuple.c +541 -0
- data/ext/util.c +6 -6
- data/ext/util.h +2 -2
- data/lib/pg.rb +5 -7
- data/lib/pg/basic_type_mapping.rb +40 -7
- data/lib/pg/binary_decoder.rb +22 -0
- data/lib/pg/coder.rb +1 -1
- data/lib/pg/connection.rb +27 -3
- data/lib/pg/constants.rb +1 -1
- data/lib/pg/exceptions.rb +1 -1
- data/lib/pg/result.rb +1 -1
- data/lib/pg/text_decoder.rb +19 -23
- data/lib/pg/text_encoder.rb +35 -1
- data/lib/pg/tuple.rb +30 -0
- data/lib/pg/type_map_by_column.rb +1 -1
- data/spec/helpers.rb +49 -21
- data/spec/pg/basic_type_mapping_spec.rb +230 -27
- data/spec/pg/connection_spec.rb +473 -277
- data/spec/pg/connection_sync_spec.rb +41 -0
- data/spec/pg/result_spec.rb +48 -13
- data/spec/pg/tuple_spec.rb +280 -0
- data/spec/pg/type_map_by_class_spec.rb +1 -1
- data/spec/pg/type_map_by_column_spec.rb +1 -1
- data/spec/pg/type_map_by_mri_type_spec.rb +1 -1
- 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 +184 -12
- data/spec/pg_spec.rb +2 -2
- metadata +37 -33
- metadata.gz.sig +0 -0
- data/lib/pg/deprecated_constants.rb +0 -21
data/spec/helpers.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# -*- ruby -*-
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
require 'rspec'
|
5
5
|
require 'shellwords'
|
6
6
|
require 'pg'
|
7
7
|
|
8
|
-
|
8
|
+
DEFAULT_TEST_DIR_STR = File.join(Dir.pwd, "tmp_test_specs")
|
9
|
+
TEST_DIR_STR = ENV['RUBY_PG_TEST_DIR'] || DEFAULT_TEST_DIR_STR
|
10
|
+
TEST_DIRECTORY = Pathname.new(TEST_DIR_STR)
|
9
11
|
|
10
12
|
module PG::TestingHelpers
|
11
13
|
|
@@ -20,12 +22,11 @@ module PG::TestingHelpers
|
|
20
22
|
|
21
23
|
mod.around( :each ) do |example|
|
22
24
|
begin
|
25
|
+
@conn.set_default_encoding
|
23
26
|
@conn.exec( 'BEGIN' ) unless example.metadata[:without_transaction]
|
24
|
-
|
25
|
-
|
26
|
-
@conn.
|
27
|
-
[@conn.escape_string(desc.slice(-60))]
|
28
|
-
end
|
27
|
+
desc = example.source_location.join(':')
|
28
|
+
@conn.exec %Q{SET application_name TO '%s'} %
|
29
|
+
[@conn.escape_string(desc.slice(-60))]
|
29
30
|
example.run
|
30
31
|
ensure
|
31
32
|
@conn.exec( 'ROLLBACK' ) unless example.metadata[:without_transaction]
|
@@ -197,8 +198,8 @@ module PG::TestingHelpers
|
|
197
198
|
@test_pgdata = TEST_DIRECTORY + 'data'
|
198
199
|
@test_pgdata.mkpath
|
199
200
|
|
200
|
-
|
201
|
-
ENV['PGPORT']
|
201
|
+
ENV['PGPORT'] ||= "54321"
|
202
|
+
@port = ENV['PGPORT'].to_i
|
202
203
|
ENV['PGHOST'] = 'localhost'
|
203
204
|
@conninfo = "host=localhost port=#{@port} dbname=test"
|
204
205
|
|
@@ -251,7 +252,7 @@ module PG::TestingHelpers
|
|
251
252
|
|
252
253
|
def check_for_lingering_connections( conn )
|
253
254
|
conn.exec( "SELECT * FROM pg_stat_activity" ) do |res|
|
254
|
-
conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid }
|
255
|
+
conns = res.find_all {|row| row['pid'].to_i != conn.backend_pid && ["client backend", nil].include?(row["backend_type"]) }
|
255
256
|
unless conns.empty?
|
256
257
|
puts "Lingering connections remain:"
|
257
258
|
conns.each do |row|
|
@@ -264,7 +265,7 @@ module PG::TestingHelpers
|
|
264
265
|
|
265
266
|
# Retrieve the names of the column types of a given result set.
|
266
267
|
def result_typenames(res)
|
267
|
-
@conn.
|
268
|
+
@conn.exec_params( "SELECT " + res.nfields.times.map{|i| "format_type($#{i*2+1},$#{i*2+2})"}.join(","),
|
268
269
|
res.nfields.times.map{|i| [res.ftype(i), res.fmod(i)] }.flatten ).
|
269
270
|
values[0]
|
270
271
|
end
|
@@ -318,6 +319,39 @@ module PG::TestingHelpers
|
|
318
319
|
return ConnStillUsableMatcher.new
|
319
320
|
end
|
320
321
|
|
322
|
+
def wait_for_polling_ok(conn, meth = :connect_poll)
|
323
|
+
status = conn.send(meth)
|
324
|
+
|
325
|
+
while status != PG::PGRES_POLLING_OK
|
326
|
+
if status == PG::PGRES_POLLING_READING
|
327
|
+
select( [conn.socket_io], [], [], 5.0 ) or
|
328
|
+
raise "Asynchronous connection timed out!"
|
329
|
+
|
330
|
+
elsif status == PG::PGRES_POLLING_WRITING
|
331
|
+
select( [], [conn.socket_io], [], 5.0 ) or
|
332
|
+
raise "Asynchronous connection timed out!"
|
333
|
+
end
|
334
|
+
status = conn.send(meth)
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def wait_for_query_result(conn)
|
339
|
+
result = nil
|
340
|
+
loop do
|
341
|
+
# Buffer any incoming data on the socket until a full result is ready.
|
342
|
+
conn.consume_input
|
343
|
+
while conn.is_busy
|
344
|
+
select( [conn.socket_io], nil, nil, 5.0 ) or
|
345
|
+
raise "Timeout waiting for query response."
|
346
|
+
conn.consume_input
|
347
|
+
end
|
348
|
+
|
349
|
+
# Fetch the next result. If there isn't one, the query is finished
|
350
|
+
result = conn.get_result || break
|
351
|
+
end
|
352
|
+
result
|
353
|
+
end
|
354
|
+
|
321
355
|
end
|
322
356
|
|
323
357
|
|
@@ -339,14 +373,8 @@ RSpec.configure do |config|
|
|
339
373
|
config.filter_run_excluding :socket_io unless
|
340
374
|
PG::Connection.instance_methods.map( &:to_sym ).include?( :socket_io )
|
341
375
|
|
342
|
-
if PG.library_version <
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
elsif PG.library_version < 90400
|
347
|
-
config.filter_run_excluding( :postgresql_94, :postgresql_95 )
|
348
|
-
elsif PG.library_version < 90500
|
349
|
-
config.filter_run_excluding( :postgresql_95 )
|
350
|
-
end
|
376
|
+
config.filter_run_excluding( :postgresql_93 ) if PG.library_version < 90300
|
377
|
+
config.filter_run_excluding( :postgresql_94 ) if PG.library_version < 90400
|
378
|
+
config.filter_run_excluding( :postgresql_95 ) if PG.library_version < 90500
|
379
|
+
config.filter_run_excluding( :postgresql_10 ) if PG.library_version < 100000
|
351
380
|
end
|
352
|
-
|
@@ -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
|
|
@@ -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,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
|
-
|
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 )
|
@@ -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.
|
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.
|
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
|