pg 1.1.3 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/ChangeLog +0 -6595
- data/History.rdoc +70 -0
- data/Manifest.txt +3 -2
- data/README-Windows.rdoc +4 -4
- data/README.ja.rdoc +1 -2
- data/README.rdoc +43 -8
- data/Rakefile +4 -4
- data/Rakefile.cross +7 -4
- data/ext/errorcodes.def +68 -0
- data/ext/errorcodes.txt +19 -2
- data/ext/extconf.rb +6 -6
- data/ext/pg.c +132 -95
- data/ext/pg.h +24 -17
- data/ext/pg_binary_decoder.c +20 -16
- data/ext/pg_binary_encoder.c +13 -12
- data/ext/pg_coder.c +5 -5
- data/ext/pg_connection.c +395 -301
- data/ext/pg_copy_coder.c +5 -3
- data/ext/pg_record_coder.c +490 -0
- data/ext/pg_result.c +272 -124
- data/ext/pg_text_decoder.c +14 -8
- data/ext/pg_text_encoder.c +180 -48
- data/ext/pg_tuple.c +14 -6
- data/ext/pg_type_map.c +1 -1
- data/ext/pg_type_map_all_strings.c +4 -4
- data/ext/pg_type_map_by_class.c +4 -3
- data/ext/pg_type_map_by_column.c +7 -6
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +3 -2
- data/ext/pg_type_map_in_ruby.c +1 -1
- data/ext/{util.c → pg_util.c} +5 -5
- data/ext/{util.h → pg_util.h} +0 -0
- data/lib/pg.rb +2 -3
- data/lib/pg/basic_type_mapping.rb +79 -16
- data/lib/pg/binary_decoder.rb +1 -0
- data/lib/pg/coder.rb +22 -1
- data/lib/pg/connection.rb +2 -2
- data/lib/pg/constants.rb +1 -0
- data/lib/pg/exceptions.rb +1 -0
- data/lib/pg/result.rb +13 -1
- data/lib/pg/text_decoder.rb +2 -3
- data/lib/pg/text_encoder.rb +8 -18
- data/lib/pg/type_map_by_column.rb +2 -1
- data/spec/helpers.rb +17 -16
- data/spec/pg/basic_type_mapping_spec.rb +151 -14
- data/spec/pg/connection_spec.rb +117 -55
- data/spec/pg/result_spec.rb +193 -3
- data/spec/pg/tuple_spec.rb +55 -2
- data/spec/pg/type_map_by_column_spec.rb +5 -1
- data/spec/pg/type_spec.rb +180 -6
- metadata +40 -45
- metadata.gz.sig +0 -0
data/lib/pg/constants.rb
CHANGED
data/lib/pg/exceptions.rb
CHANGED
data/lib/pg/result.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'pg' unless defined?( PG )
|
4
5
|
|
@@ -9,12 +10,23 @@ class PG::Result
|
|
9
10
|
#
|
10
11
|
# +type_map+: a PG::TypeMap instance.
|
11
12
|
#
|
12
|
-
#
|
13
|
+
# This method is equal to #type_map= , but returns self, so that calls can be chained.
|
14
|
+
#
|
15
|
+
# See also PG::BasicTypeMapForResults
|
13
16
|
def map_types!(type_map)
|
14
17
|
self.type_map = type_map
|
15
18
|
return self
|
16
19
|
end
|
17
20
|
|
21
|
+
# Set the data type for all field name returning methods.
|
22
|
+
#
|
23
|
+
# +type+: a Symbol defining the field name type.
|
24
|
+
#
|
25
|
+
# This method is equal to #field_name_type= , but returns self, so that calls can be chained.
|
26
|
+
def field_names_as(type)
|
27
|
+
self.field_name_type = type
|
28
|
+
return self
|
29
|
+
end
|
18
30
|
|
19
31
|
### Return a String representation of the object suitable for debugging.
|
20
32
|
def inspect
|
data/lib/pg/text_decoder.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'date'
|
4
5
|
require 'json'
|
@@ -6,10 +7,8 @@ require 'json'
|
|
6
7
|
module PG
|
7
8
|
module TextDecoder
|
8
9
|
class Date < SimpleDecoder
|
9
|
-
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
10
|
-
|
11
10
|
def decode(string, tuple=nil, field=nil)
|
12
|
-
if string =~
|
11
|
+
if string =~ /\A(\d{4})-(\d\d)-(\d\d)\z/
|
13
12
|
::Date.new $1.to_i, $2.to_i, $3.to_i
|
14
13
|
else
|
15
14
|
string
|
data/lib/pg/text_encoder.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'json'
|
4
5
|
require 'ipaddr'
|
@@ -6,36 +7,26 @@ require 'ipaddr'
|
|
6
7
|
module PG
|
7
8
|
module TextEncoder
|
8
9
|
class Date < SimpleEncoder
|
9
|
-
STRFTIME_ISO_DATE = "%Y-%m-%d".freeze
|
10
10
|
def encode(value)
|
11
|
-
value.respond_to?(:strftime) ? value.strftime(
|
11
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d") : value
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
class TimestampWithoutTimeZone < SimpleEncoder
|
16
|
-
STRFTIME_ISO_DATETIME_WITHOUT_TIMEZONE = "%Y-%m-%d %H:%M:%S.%N".freeze
|
17
16
|
def encode(value)
|
18
|
-
value.respond_to?(:strftime) ? value.strftime(
|
17
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N") : value
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
22
21
|
class TimestampUtc < SimpleEncoder
|
23
|
-
STRFTIME_ISO_DATETIME_WITHOUT_TIMEZONE_UTC = "%Y-%m-%d %H:%M:%S.%N".freeze
|
24
22
|
def encode(value)
|
25
|
-
value.respond_to?(:utc) ? value.utc.strftime(
|
23
|
+
value.respond_to?(:utc) ? value.utc.strftime("%Y-%m-%d %H:%M:%S.%N") : value
|
26
24
|
end
|
27
25
|
end
|
28
26
|
|
29
27
|
class TimestampWithTimeZone < SimpleEncoder
|
30
|
-
STRFTIME_ISO_DATETIME_WITH_TIMEZONE = "%Y-%m-%d %H:%M:%S.%N %:z".freeze
|
31
28
|
def encode(value)
|
32
|
-
value.respond_to?(:strftime) ? value.strftime(
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
class Numeric < SimpleEncoder
|
37
|
-
def encode(value)
|
38
|
-
value.is_a?(BigDecimal) ? value.to_s('F') : value
|
29
|
+
value.respond_to?(:strftime) ? value.strftime("%Y-%m-%d %H:%M:%S.%N %:z") : value
|
39
30
|
end
|
40
31
|
end
|
41
32
|
|
@@ -51,12 +42,12 @@ module PG
|
|
51
42
|
when IPAddr
|
52
43
|
default_prefix = (value.family == Socket::AF_INET ? 32 : 128)
|
53
44
|
s = value.to_s
|
54
|
-
|
45
|
+
if value.respond_to?(:prefix)
|
55
46
|
prefix = value.prefix
|
56
|
-
|
47
|
+
else
|
57
48
|
range = value.to_range
|
58
49
|
prefix = default_prefix - Math.log(((range.end.to_i - range.begin.to_i) + 1), 2).to_i
|
59
|
-
|
50
|
+
end
|
60
51
|
s << "/" << prefix.to_s if prefix != default_prefix
|
61
52
|
s
|
62
53
|
else
|
@@ -66,4 +57,3 @@ module PG
|
|
66
57
|
end
|
67
58
|
end
|
68
59
|
end # module PG
|
69
|
-
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
require 'pg' unless defined?( PG )
|
4
5
|
|
@@ -9,7 +10,7 @@ class PG::TypeMapByColumn
|
|
9
10
|
end
|
10
11
|
|
11
12
|
def inspect
|
12
|
-
type_strings = coders.map{|c| c ?
|
13
|
+
type_strings = coders.map{|c| c ? c.inspect_short : 'nil' }
|
13
14
|
"#<#{self.class} #{type_strings.join(' ')}>"
|
14
15
|
end
|
15
16
|
end
|
data/spec/helpers.rb
CHANGED
@@ -172,18 +172,18 @@ module PG::TestingHelpers
|
|
172
172
|
datadir = testdir + 'data'
|
173
173
|
pidfile = datadir + 'postmaster.pid'
|
174
174
|
if pidfile.exist? && pid = pidfile.read.chomp.to_i
|
175
|
-
|
175
|
+
trace "pidfile (%p) exists: %d" % [ pidfile, pid ]
|
176
176
|
begin
|
177
177
|
Process.kill( 0, pid )
|
178
178
|
rescue Errno::ESRCH
|
179
|
-
|
179
|
+
trace "No postmaster running for %s" % [ datadir ]
|
180
180
|
# Process isn't alive, so don't try to stop it
|
181
181
|
else
|
182
|
-
|
182
|
+
trace "Stopping lingering database at PID %d" % [ pid ]
|
183
183
|
run 'pg_ctl', '-D', datadir.to_s, '-m', 'fast', 'stop'
|
184
184
|
end
|
185
185
|
else
|
186
|
-
|
186
|
+
trace "No pidfile (%p)" % [ pidfile ]
|
187
187
|
end
|
188
188
|
end
|
189
189
|
end
|
@@ -194,12 +194,12 @@ module PG::TestingHelpers
|
|
194
194
|
require 'pg'
|
195
195
|
stop_existing_postmasters()
|
196
196
|
|
197
|
-
|
197
|
+
trace "Setting up test database for #{description}"
|
198
198
|
@test_pgdata = TEST_DIRECTORY + 'data'
|
199
199
|
@test_pgdata.mkpath
|
200
200
|
|
201
|
-
|
202
|
-
ENV['PGPORT']
|
201
|
+
ENV['PGPORT'] ||= "54321"
|
202
|
+
@port = ENV['PGPORT'].to_i
|
203
203
|
ENV['PGHOST'] = 'localhost'
|
204
204
|
@conninfo = "host=localhost port=#{@port} dbname=test"
|
205
205
|
|
@@ -209,7 +209,7 @@ module PG::TestingHelpers
|
|
209
209
|
begin
|
210
210
|
unless (@test_pgdata+"postgresql.conf").exist?
|
211
211
|
FileUtils.rm_rf( @test_pgdata, :verbose => $DEBUG )
|
212
|
-
|
212
|
+
trace "Running initdb"
|
213
213
|
log_and_run @logfile, 'initdb', '-E', 'UTF8', '--no-locale', '-D', @test_pgdata.to_s
|
214
214
|
end
|
215
215
|
|
@@ -218,7 +218,7 @@ module PG::TestingHelpers
|
|
218
218
|
'-D', @test_pgdata.to_s, 'start'
|
219
219
|
sleep 2
|
220
220
|
|
221
|
-
|
221
|
+
trace "Creating the test DB"
|
222
222
|
log_and_run @logfile, 'psql', '-e', '-c', 'DROP DATABASE IF EXISTS test', 'postgres'
|
223
223
|
log_and_run @logfile, 'createdb', '-e', 'test'
|
224
224
|
|
@@ -239,7 +239,7 @@ module PG::TestingHelpers
|
|
239
239
|
|
240
240
|
|
241
241
|
def teardown_testing_db( conn )
|
242
|
-
|
242
|
+
trace "Tearing down test database"
|
243
243
|
|
244
244
|
if conn
|
245
245
|
check_for_lingering_connections( conn )
|
@@ -319,20 +319,19 @@ module PG::TestingHelpers
|
|
319
319
|
return ConnStillUsableMatcher.new
|
320
320
|
end
|
321
321
|
|
322
|
-
def wait_for_polling_ok(conn)
|
323
|
-
|
324
|
-
status = conn.connect_poll
|
322
|
+
def wait_for_polling_ok(conn, meth = :connect_poll)
|
323
|
+
status = conn.send(meth)
|
325
324
|
|
326
325
|
while status != PG::PGRES_POLLING_OK
|
327
326
|
if status == PG::PGRES_POLLING_READING
|
328
|
-
select( [
|
327
|
+
select( [conn.socket_io], [], [], 5.0 ) or
|
329
328
|
raise "Asynchronous connection timed out!"
|
330
329
|
|
331
330
|
elsif status == PG::PGRES_POLLING_WRITING
|
332
|
-
select( [], [
|
331
|
+
select( [], [conn.socket_io], [], 5.0 ) or
|
333
332
|
raise "Asynchronous connection timed out!"
|
334
333
|
end
|
335
|
-
status = conn.
|
334
|
+
status = conn.send(meth)
|
336
335
|
end
|
337
336
|
end
|
338
337
|
|
@@ -377,5 +376,7 @@ RSpec.configure do |config|
|
|
377
376
|
config.filter_run_excluding( :postgresql_93 ) if PG.library_version < 90300
|
378
377
|
config.filter_run_excluding( :postgresql_94 ) if PG.library_version < 90400
|
379
378
|
config.filter_run_excluding( :postgresql_95 ) if PG.library_version < 90500
|
379
|
+
config.filter_run_excluding( :postgresql_96 ) if PG.library_version < 90600
|
380
380
|
config.filter_run_excluding( :postgresql_10 ) if PG.library_version < 100000
|
381
|
+
config.filter_run_excluding( :postgresql_12 ) if PG.library_version < 120000
|
381
382
|
end
|
@@ -21,6 +21,14 @@ ensure
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
+
def expect_to_typecase_result_value_warning
|
25
|
+
warning = 'Warning: no type cast defined for type "name" with oid 19. '\
|
26
|
+
"Please cast this type explicitly to TEXT to be safe for future changes.\n"\
|
27
|
+
'Warning: no type cast defined for type "regproc" with oid 24. '\
|
28
|
+
"Please cast this type explicitly to TEXT to be safe for future changes.\n"
|
29
|
+
expect { yield }.to output(warning).to_stderr
|
30
|
+
end
|
31
|
+
|
24
32
|
describe 'Basic type mapping' do
|
25
33
|
|
26
34
|
describe PG::BasicTypeMapForQueries do
|
@@ -32,8 +40,8 @@ describe 'Basic type mapping' do
|
|
32
40
|
# Encoding Examples
|
33
41
|
#
|
34
42
|
|
35
|
-
it "should do basic param encoding"
|
36
|
-
res = @conn.exec_params( "SELECT $1::int8
|
43
|
+
it "should do basic param encoding" do
|
44
|
+
res = @conn.exec_params( "SELECT $1::int8, $2::float, $3, $4::TEXT",
|
37
45
|
[1, 2.1, true, "b"], nil, basic_type_mapping )
|
38
46
|
|
39
47
|
expect( res.values ).to eq( [
|
@@ -43,26 +51,132 @@ describe 'Basic type mapping' do
|
|
43
51
|
expect( result_typenames(res) ).to eq( ['bigint', 'double precision', 'boolean', 'text'] )
|
44
52
|
end
|
45
53
|
|
46
|
-
it "should do
|
47
|
-
res = @conn.exec_params( "SELECT $1
|
48
|
-
|
49
|
-
|
50
|
-
|
54
|
+
it "should do basic Time encoding" do
|
55
|
+
res = @conn.exec_params( "SELECT $1 AT TIME ZONE '-02'",
|
56
|
+
[Time.new(2019, 12, 8, 20, 38, 12.123, "-01:00")], nil, basic_type_mapping )
|
57
|
+
|
58
|
+
expect( res.values ).to eq( [[ "2019-12-08 23:38:12.123" ]] )
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should do basic param encoding of various float values" do
|
62
|
+
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",
|
63
|
+
[0, 7, 9, 0.1, 0.9, -0.11, 10.11,
|
64
|
+
9876543210987654321e-400,
|
65
|
+
9876543210987654321e400,
|
66
|
+
-1.234567890123456789e-280,
|
67
|
+
-1.234567890123456789e280,
|
68
|
+
9876543210987654321e280
|
69
|
+
], nil, basic_type_mapping )
|
70
|
+
|
71
|
+
expect( res.values[0][0, 9] ).to eq(
|
72
|
+
[ "0", "7", "9", "0.1", "0.9", "-0.11", "10.11", "0", "Infinity" ]
|
73
|
+
)
|
74
|
+
|
75
|
+
expect( res.values[0][9] ).to match( /^-1\.2345678901234\d*e\-280$/ )
|
76
|
+
expect( res.values[0][10] ).to match( /^-1\.2345678901234\d*e\+280$/ )
|
77
|
+
expect( res.values[0][11] ).to match( /^9\.8765432109876\d*e\+298$/ )
|
78
|
+
|
79
|
+
expect( result_typenames(res) ).to eq( ['double precision'] * 12 )
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should do default array-as-array param encoding" do
|
83
|
+
expect( basic_type_mapping.encode_array_as).to eq(:array)
|
84
|
+
res = @conn.exec_params( "SELECT $1,$2,$3,$4,$5,$6", [
|
85
|
+
[1, 2, 3], # Integer -> bigint[]
|
86
|
+
[[1, 2], [3, nil]], # Integer two dimensions -> bigint[]
|
87
|
+
[1.11, 2.21], # Float -> double precision[]
|
88
|
+
['/,"'.gsub("/", "\\"), nil, 'abcäöü'], # String -> text[]
|
89
|
+
[BigDecimal("123.45")], # BigDecimal -> numeric[]
|
90
|
+
[IPAddr.new('1234::5678')], # IPAddr -> inet[]
|
51
91
|
], nil, basic_type_mapping )
|
52
92
|
|
53
93
|
expect( res.values ).to eq( [[
|
54
|
-
'{1,2,3}',
|
94
|
+
'{1,2,3}',
|
95
|
+
'{{1,2},{3,NULL}}',
|
55
96
|
'{1.11,2.21}',
|
56
97
|
'{"//,/"",NULL,abcäöü}'.gsub("/", "\\"),
|
98
|
+
'{123.45}',
|
99
|
+
'{1234::5678}',
|
57
100
|
]] )
|
58
101
|
|
59
|
-
expect( result_typenames(res) ).to eq( ['bigint[]', 'bigint[]', 'double precision[]', 'text[]'] )
|
102
|
+
expect( result_typenames(res) ).to eq( ['bigint[]', 'bigint[]', 'double precision[]', 'text[]', 'numeric[]', 'inet[]'] )
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should do default array-as-array param encoding with Time objects" do
|
106
|
+
res = @conn.exec_params( "SELECT $1", [
|
107
|
+
[Time.new(2019, 12, 8, 20, 38, 12.123, "-01:00")], # Time -> timestamptz[]
|
108
|
+
], nil, basic_type_mapping )
|
109
|
+
|
110
|
+
expect( res.values[0][0] ).to match( /\{\"2019-12-08 \d\d:38:12.123[+-]\d\d\"\}/ )
|
111
|
+
expect( result_typenames(res) ).to eq( ['timestamp with time zone[]'] )
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should do array-as-json encoding" do
|
115
|
+
basic_type_mapping.encode_array_as = :json
|
116
|
+
expect( basic_type_mapping.encode_array_as).to eq(:json)
|
117
|
+
|
118
|
+
res = @conn.exec_params( "SELECT $1::JSON, $2::JSON", [
|
119
|
+
[1, {a: 5}, true, ["a", 2], [3.4, nil]],
|
120
|
+
['/,"'.gsub("/", "\\"), nil, 'abcäöü'],
|
121
|
+
], nil, basic_type_mapping )
|
122
|
+
|
123
|
+
expect( res.values ).to eq( [[
|
124
|
+
'[1,{"a":5},true,["a",2],[3.4,null]]',
|
125
|
+
'["//,/"",null,"abcäöü"]'.gsub("/", "\\"),
|
126
|
+
]] )
|
127
|
+
|
128
|
+
expect( result_typenames(res) ).to eq( ['json', 'json'] )
|
129
|
+
end
|
130
|
+
|
131
|
+
it "should do hash-as-json encoding" do
|
132
|
+
res = @conn.exec_params( "SELECT $1::JSON, $2::JSON", [
|
133
|
+
{a: 5, b: ["a", 2], c: nil},
|
134
|
+
{qu: '/,"'.gsub("/", "\\"), ni: nil, uml: 'abcäöü'},
|
135
|
+
], nil, basic_type_mapping )
|
136
|
+
|
137
|
+
expect( res.values ).to eq( [[
|
138
|
+
'{"a":5,"b":["a",2],"c":null}',
|
139
|
+
'{"qu":"//,/"","ni":null,"uml":"abcäöü"}'.gsub("/", "\\"),
|
140
|
+
]] )
|
141
|
+
|
142
|
+
expect( result_typenames(res) ).to eq( ['json', 'json'] )
|
143
|
+
end
|
144
|
+
|
145
|
+
describe "Record encoding" do
|
146
|
+
before :all do
|
147
|
+
@conn.exec("CREATE TYPE test_record1 AS (i int, d float, t text)")
|
148
|
+
@conn.exec("CREATE TYPE test_record2 AS (i int, r test_record1)")
|
149
|
+
end
|
150
|
+
|
151
|
+
after :all do
|
152
|
+
@conn.exec("DROP TYPE IF EXISTS test_record2 CASCADE")
|
153
|
+
@conn.exec("DROP TYPE IF EXISTS test_record1 CASCADE")
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should do array-as-record encoding" do
|
157
|
+
basic_type_mapping.encode_array_as = :record
|
158
|
+
expect( basic_type_mapping.encode_array_as).to eq(:record)
|
159
|
+
|
160
|
+
res = @conn.exec_params( "SELECT $1::test_record1, $2::test_record2, $3::text", [
|
161
|
+
[5, 3.4, "txt"],
|
162
|
+
[1, [2, 4.5, "bcd"]],
|
163
|
+
[4, 5, 6],
|
164
|
+
], nil, basic_type_mapping )
|
165
|
+
|
166
|
+
expect( res.values ).to eq( [[
|
167
|
+
'(5,3.4,txt)',
|
168
|
+
'(1,"(2,4.5,bcd)")',
|
169
|
+
'("4","5","6")',
|
170
|
+
]] )
|
171
|
+
|
172
|
+
expect( result_typenames(res) ).to eq( ['test_record1', 'test_record2', 'text'] )
|
173
|
+
end
|
60
174
|
end
|
61
175
|
|
62
176
|
it "should do bigdecimal param encoding" do
|
63
177
|
large = ('123456790'*10) << '.' << ('012345679')
|
64
178
|
res = @conn.exec_params( "SELECT $1::numeric,$2::numeric",
|
65
|
-
[BigDecimal
|
179
|
+
[BigDecimal('1'), BigDecimal(large)], nil, basic_type_mapping )
|
66
180
|
|
67
181
|
expect( res.values ).to eq( [
|
68
182
|
[ "1.0", large ],
|
@@ -82,6 +196,23 @@ describe 'Basic type mapping' do
|
|
82
196
|
expect( result_typenames(res) ).to eq( ['inet', 'inet', 'cidr', 'cidr'] )
|
83
197
|
end
|
84
198
|
|
199
|
+
it "should do array of string encoding on unknown classes" do
|
200
|
+
iv = Class.new do
|
201
|
+
def to_s
|
202
|
+
"abc"
|
203
|
+
end
|
204
|
+
end.new
|
205
|
+
res = @conn.exec_params( "SELECT $1", [
|
206
|
+
[iv, iv], # Unknown -> text[]
|
207
|
+
], nil, basic_type_mapping )
|
208
|
+
|
209
|
+
expect( res.values ).to eq( [[
|
210
|
+
'{abc,abc}',
|
211
|
+
]] )
|
212
|
+
|
213
|
+
expect( result_typenames(res) ).to eq( ['text[]'] )
|
214
|
+
end
|
215
|
+
|
85
216
|
end
|
86
217
|
|
87
218
|
|
@@ -95,7 +226,7 @@ describe 'Basic type mapping' do
|
|
95
226
|
# Decoding Examples
|
96
227
|
#
|
97
228
|
|
98
|
-
it "should do OID based type conversions"
|
229
|
+
it "should do OID based type conversions" do
|
99
230
|
res = @conn.exec( "SELECT 1, 'a', 2.0::FLOAT, TRUE, '2013-06-30'::DATE, generate_series(4,5)" )
|
100
231
|
expect( res.map_types!(basic_type_mapping).values ).to eq( [
|
101
232
|
[ 1, 'a', 2.0, true, Date.new(2013,6,30), 4 ],
|
@@ -187,7 +318,9 @@ describe 'Basic type mapping' do
|
|
187
318
|
it "should convert format #{format} timestamps per TimestampUtc" do
|
188
319
|
restore_type("timestamp") do
|
189
320
|
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampUtc
|
190
|
-
|
321
|
+
expect_to_typecase_result_value_warning do
|
322
|
+
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
323
|
+
end
|
191
324
|
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
192
325
|
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
193
326
|
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
@@ -209,7 +342,9 @@ describe 'Basic type mapping' do
|
|
209
342
|
restore_type("timestamp") do
|
210
343
|
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampUtcToLocal
|
211
344
|
PG::BasicTypeRegistry.register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampUtcToLocal
|
212
|
-
|
345
|
+
expect_to_typecase_result_value_warning do
|
346
|
+
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
347
|
+
end
|
213
348
|
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59+02' AS TIMESTAMP WITHOUT TIME ZONE),
|
214
349
|
CAST('1913-12-31 23:58:59.1231-03' AS TIMESTAMP WITHOUT TIME ZONE),
|
215
350
|
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|
@@ -231,7 +366,9 @@ describe 'Basic type mapping' do
|
|
231
366
|
restore_type("timestamp") do
|
232
367
|
PG::BasicTypeRegistry.register_type 0, 'timestamp', nil, PG::TextDecoder::TimestampLocal
|
233
368
|
PG::BasicTypeRegistry.register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampLocal
|
234
|
-
|
369
|
+
expect_to_typecase_result_value_warning do
|
370
|
+
@conn.type_map_for_results = PG::BasicTypeMapForResults.new(@conn)
|
371
|
+
end
|
235
372
|
res = @conn.exec_params( "SELECT CAST('2013-07-31 23:58:59' AS TIMESTAMP WITHOUT TIME ZONE),
|
236
373
|
CAST('1913-12-31 23:58:59.1231' AS TIMESTAMP WITHOUT TIME ZONE),
|
237
374
|
CAST('4714-11-24 23:58:59.1231-03 BC' AS TIMESTAMP WITHOUT TIME ZONE),
|