pg 1.3.3 → 1.5.3
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 +15 -9
- data/.github/workflows/binary-gems.yml +43 -12
- data/.github/workflows/source-gem.yml +28 -20
- data/.gitignore +11 -2
- data/.travis.yml +2 -2
- data/{History.rdoc → History.md} +302 -115
- data/README.ja.md +276 -0
- data/README.md +286 -0
- data/Rakefile +15 -6
- data/Rakefile.cross +7 -11
- data/certs/larskanis-2023.pem +24 -0
- data/ext/errorcodes.def +4 -0
- data/ext/errorcodes.rb +0 -0
- data/ext/errorcodes.txt +2 -1
- data/ext/extconf.rb +0 -0
- data/ext/pg.c +14 -54
- data/ext/pg.h +12 -5
- data/ext/pg_binary_decoder.c +80 -1
- data/ext/pg_binary_encoder.c +225 -1
- data/ext/pg_coder.c +17 -8
- data/ext/pg_connection.c +385 -266
- data/ext/pg_copy_coder.c +307 -18
- data/ext/pg_errors.c +1 -1
- data/ext/pg_record_coder.c +12 -9
- data/ext/pg_result.c +117 -34
- data/ext/pg_text_decoder.c +28 -10
- data/ext/pg_text_encoder.c +23 -10
- data/ext/pg_tuple.c +36 -39
- data/ext/pg_type_map.c +4 -3
- data/ext/pg_type_map_all_strings.c +3 -3
- data/ext/pg_type_map_by_class.c +6 -4
- data/ext/pg_type_map_by_column.c +9 -5
- data/ext/pg_type_map_by_mri_type.c +1 -1
- data/ext/pg_type_map_by_oid.c +8 -5
- data/ext/pg_type_map_in_ruby.c +6 -3
- data/lib/pg/basic_type_map_based_on_result.rb +21 -1
- data/lib/pg/basic_type_map_for_queries.rb +13 -8
- data/lib/pg/basic_type_map_for_results.rb +26 -3
- data/lib/pg/basic_type_registry.rb +36 -33
- data/lib/pg/binary_decoder/date.rb +9 -0
- data/lib/pg/binary_decoder/timestamp.rb +26 -0
- data/lib/pg/binary_encoder/timestamp.rb +20 -0
- data/lib/pg/coder.rb +15 -13
- data/lib/pg/connection.rb +269 -139
- data/lib/pg/exceptions.rb +14 -1
- data/lib/pg/text_decoder/date.rb +18 -0
- data/lib/pg/text_decoder/inet.rb +9 -0
- data/lib/pg/text_decoder/json.rb +14 -0
- data/lib/pg/text_decoder/numeric.rb +9 -0
- data/lib/pg/text_decoder/timestamp.rb +30 -0
- data/lib/pg/text_encoder/date.rb +12 -0
- data/lib/pg/text_encoder/inet.rb +28 -0
- data/lib/pg/text_encoder/json.rb +14 -0
- data/lib/pg/text_encoder/numeric.rb +9 -0
- data/lib/pg/text_encoder/timestamp.rb +24 -0
- data/lib/pg/version.rb +1 -1
- data/lib/pg.rb +59 -19
- data/misc/openssl-pg-segfault.rb +0 -0
- data/pg.gemspec +4 -2
- data/rakelib/task_extension.rb +1 -1
- data/sample/array_insert.rb +0 -0
- data/sample/async_api.rb +3 -7
- data/sample/async_copyto.rb +0 -0
- data/sample/async_mixed.rb +0 -0
- data/sample/check_conn.rb +0 -0
- data/sample/copydata.rb +0 -0
- data/sample/copyfrom.rb +0 -0
- data/sample/copyto.rb +0 -0
- data/sample/cursor.rb +0 -0
- data/sample/disk_usage_report.rb +0 -0
- data/sample/issue-119.rb +0 -0
- data/sample/losample.rb +0 -0
- data/sample/minimal-testcase.rb +0 -0
- data/sample/notify_wait.rb +0 -0
- data/sample/pg_statistics.rb +0 -0
- data/sample/replication_monitor.rb +0 -0
- data/sample/test_binary_values.rb +0 -0
- data/sample/wal_shipper.rb +0 -0
- data/sample/warehouse_partitions.rb +0 -0
- data/translation/.po4a-version +7 -0
- data/translation/po/all.pot +910 -0
- data/translation/po/ja.po +1047 -0
- data/translation/po4a.cfg +12 -0
- data.tar.gz.sig +0 -0
- metadata +101 -32
- metadata.gz.sig +0 -0
- data/README.ja.rdoc +0 -13
- data/README.rdoc +0 -214
- data/lib/pg/binary_decoder.rb +0 -23
- data/lib/pg/constants.rb +0 -12
- data/lib/pg/text_decoder.rb +0 -46
- data/lib/pg/text_encoder.rb +0 -59
@@ -22,7 +22,7 @@ require 'pg' unless defined?( PG )
|
|
22
22
|
# end
|
23
23
|
#
|
24
24
|
# conn = PG.connect
|
25
|
-
# regi = PG::BasicTypeRegistry.new.
|
25
|
+
# regi = PG::BasicTypeRegistry.new.register_default_types
|
26
26
|
# regi.register_type(0, 'inet', InetEncoder, InetDecoder)
|
27
27
|
# conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn, registry: regi)
|
28
28
|
class PG::BasicTypeRegistry
|
@@ -39,7 +39,8 @@ class PG::BasicTypeRegistry
|
|
39
39
|
oid
|
40
40
|
bool
|
41
41
|
date timestamp timestamptz
|
42
|
-
].inject({}){|h,e| h[e] = true; h }
|
42
|
+
].inject({}){|h,e| h[e] = true; h }.freeze
|
43
|
+
private_constant :DONT_QUOTE_TYPES
|
43
44
|
|
44
45
|
def initialize(result, coders_by_name, format, arraycoder)
|
45
46
|
coder_map = {}
|
@@ -52,7 +53,7 @@ class PG::BasicTypeRegistry
|
|
52
53
|
coder.oid = row['oid'].to_i
|
53
54
|
coder.name = row['typname']
|
54
55
|
coder.format = format
|
55
|
-
coder_map[coder.oid] = coder
|
56
|
+
coder_map[coder.oid] = coder.freeze
|
56
57
|
end
|
57
58
|
|
58
59
|
if arraycoder
|
@@ -67,13 +68,14 @@ class PG::BasicTypeRegistry
|
|
67
68
|
coder.format = format
|
68
69
|
coder.elements_type = elements_coder
|
69
70
|
coder.needs_quotation = !DONT_QUOTE_TYPES[elements_coder.name]
|
70
|
-
coder_map[coder.oid] = coder
|
71
|
+
coder_map[coder.oid] = coder.freeze
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
74
|
-
@coders = coder_map.values
|
75
|
-
@coders_by_name = @coders.inject({}){|h, t| h[t.name] = t; h }
|
76
|
-
@coders_by_oid = @coders.inject({}){|h, t| h[t.oid] = t; h }
|
75
|
+
@coders = coder_map.values.freeze
|
76
|
+
@coders_by_name = @coders.inject({}){|h, t| h[t.name] = t; h }.freeze
|
77
|
+
@coders_by_oid = @coders.inject({}){|h, t| h[t.oid] = t; h }.freeze
|
78
|
+
freeze
|
77
79
|
end
|
78
80
|
|
79
81
|
attr_reader :coders
|
@@ -117,6 +119,11 @@ class PG::BasicTypeRegistry
|
|
117
119
|
JOIN pg_proc as ti ON ti.oid = t.typinput
|
118
120
|
SQL
|
119
121
|
|
122
|
+
init_maps(registry, result.freeze)
|
123
|
+
freeze
|
124
|
+
end
|
125
|
+
|
126
|
+
private def init_maps(registry, result)
|
120
127
|
@maps = [
|
121
128
|
[0, :encoder, PG::TextEncoder::Array],
|
122
129
|
[0, :decoder, PG::TextDecoder::Array],
|
@@ -127,9 +134,9 @@ class PG::BasicTypeRegistry
|
|
127
134
|
h[format] ||= {}
|
128
135
|
h[format][direction] = CoderMap.new(result, coders, format, arraycoder)
|
129
136
|
h
|
130
|
-
end
|
137
|
+
end.each{|h| h.freeze }.freeze
|
131
138
|
|
132
|
-
@typenames_by_oid = result.inject({}){|h, t| h[t['oid'].to_i] = t['typname']; h }
|
139
|
+
@typenames_by_oid = result.inject({}){|h, t| h[t['oid'].to_i] = t['typname']; h }.freeze
|
133
140
|
end
|
134
141
|
|
135
142
|
def each_format(direction)
|
@@ -142,8 +149,9 @@ class PG::BasicTypeRegistry
|
|
142
149
|
end
|
143
150
|
|
144
151
|
module Checker
|
145
|
-
ValidFormats = { 0 => true, 1 => true }
|
146
|
-
ValidDirections = { :encoder => true, :decoder => true }
|
152
|
+
ValidFormats = { 0 => true, 1 => true }.freeze
|
153
|
+
ValidDirections = { :encoder => true, :decoder => true }.freeze
|
154
|
+
private_constant :ValidFormats, :ValidDirections
|
147
155
|
|
148
156
|
protected def check_format_and_direction(format, direction)
|
149
157
|
raise(ArgumentError, "Invalid format value %p" % format) unless ValidFormats[format]
|
@@ -155,7 +163,7 @@ class PG::BasicTypeRegistry
|
|
155
163
|
raise ArgumentError, "registry argument must be given to CoderMapsBundle" if registry
|
156
164
|
conn_or_maps
|
157
165
|
else
|
158
|
-
PG::BasicTypeRegistry::CoderMapsBundle.new(conn_or_maps, registry: registry)
|
166
|
+
PG::BasicTypeRegistry::CoderMapsBundle.new(conn_or_maps, registry: registry).freeze
|
159
167
|
end
|
160
168
|
end
|
161
169
|
end
|
@@ -184,6 +192,7 @@ class PG::BasicTypeRegistry
|
|
184
192
|
name = coder.name || raise(ArgumentError, "name of #{coder.inspect} must be defined")
|
185
193
|
h[:encoder][name] = coder if coder.respond_to?(:encode)
|
186
194
|
h[:decoder][name] = coder if coder.respond_to?(:decode)
|
195
|
+
self
|
187
196
|
end
|
188
197
|
|
189
198
|
# Register the given +encoder_class+ and/or +decoder_class+ for casting a PostgreSQL type.
|
@@ -191,8 +200,9 @@ class PG::BasicTypeRegistry
|
|
191
200
|
# +name+ must correspond to the +typname+ column in the +pg_type+ table.
|
192
201
|
# +format+ can be 0 for text format and 1 for binary.
|
193
202
|
def register_type(format, name, encoder_class, decoder_class)
|
194
|
-
register_coder(encoder_class.new(name: name, format: format)) if encoder_class
|
195
|
-
register_coder(decoder_class.new(name: name, format: format)) if decoder_class
|
203
|
+
register_coder(encoder_class.new(name: name, format: format).freeze) if encoder_class
|
204
|
+
register_coder(decoder_class.new(name: name, format: format).freeze) if decoder_class
|
205
|
+
self
|
196
206
|
end
|
197
207
|
|
198
208
|
# Alias the +old+ type to the +new+ type.
|
@@ -205,10 +215,11 @@ class PG::BasicTypeRegistry
|
|
205
215
|
@coders_by_name[format][ende].delete(new)
|
206
216
|
end
|
207
217
|
end
|
218
|
+
self
|
208
219
|
end
|
209
220
|
|
210
221
|
# Populate the registry with all builtin types of ruby-pg
|
211
|
-
def
|
222
|
+
def register_default_types
|
212
223
|
register_type 0, 'int2', PG::TextEncoder::Integer, PG::TextDecoder::Integer
|
213
224
|
alias_type 0, 'int4', 'int2'
|
214
225
|
alias_type 0, 'int8', 'int2'
|
@@ -229,9 +240,7 @@ class PG::BasicTypeRegistry
|
|
229
240
|
# alias_type 'uuid', 'text'
|
230
241
|
#
|
231
242
|
# register_type 'money', OID::Money.new
|
232
|
-
|
233
|
-
# in binary format, either with PG::BinaryEncoder::Bytea or in Hash param format.
|
234
|
-
register_type 0, 'bytea', nil, PG::TextDecoder::Bytea
|
243
|
+
register_type 0, 'bytea', PG::TextEncoder::Bytea, PG::TextDecoder::Bytea
|
235
244
|
register_type 0, 'bool', PG::TextEncoder::Boolean, PG::TextDecoder::Boolean
|
236
245
|
# register_type 'bit', OID::Bit.new
|
237
246
|
# register_type 'varbit', OID::Bit.new
|
@@ -239,6 +248,7 @@ class PG::BasicTypeRegistry
|
|
239
248
|
register_type 0, 'float4', PG::TextEncoder::Float, PG::TextDecoder::Float
|
240
249
|
alias_type 0, 'float8', 'float4'
|
241
250
|
|
251
|
+
# For compatibility reason the timestamp in text format is encoded as local time (TimestampWithoutTimeZone) instead of UTC
|
242
252
|
register_type 0, 'timestamp', PG::TextEncoder::TimestampWithoutTimeZone, PG::TextDecoder::TimestampWithoutTimeZone
|
243
253
|
register_type 0, 'timestamptz', PG::TextEncoder::TimestampWithTimeZone, PG::TextDecoder::TimestampWithTimeZone
|
244
254
|
register_type 0, 'date', PG::TextEncoder::Date, PG::TextDecoder::Date
|
@@ -273,24 +283,17 @@ class PG::BasicTypeRegistry
|
|
273
283
|
|
274
284
|
register_type 1, 'bytea', PG::BinaryEncoder::Bytea, PG::BinaryDecoder::Bytea
|
275
285
|
register_type 1, 'bool', PG::BinaryEncoder::Boolean, PG::BinaryDecoder::Boolean
|
276
|
-
register_type 1, 'float4',
|
277
|
-
register_type 1, 'float8',
|
278
|
-
register_type 1, 'timestamp',
|
279
|
-
register_type 1, 'timestamptz',
|
286
|
+
register_type 1, 'float4', PG::BinaryEncoder::Float4, PG::BinaryDecoder::Float
|
287
|
+
register_type 1, 'float8', PG::BinaryEncoder::Float8, PG::BinaryDecoder::Float
|
288
|
+
register_type 1, 'timestamp', PG::BinaryEncoder::TimestampUtc, PG::BinaryDecoder::TimestampUtc
|
289
|
+
register_type 1, 'timestamptz', PG::BinaryEncoder::TimestampUtc, PG::BinaryDecoder::TimestampUtcToLocal
|
290
|
+
register_type 1, 'date', PG::BinaryEncoder::Date, PG::BinaryDecoder::Date
|
280
291
|
|
281
292
|
self
|
282
293
|
end
|
283
294
|
|
284
|
-
|
285
|
-
DEFAULT_TYPE_REGISTRY = PG::BasicTypeRegistry.new.define_default_types
|
295
|
+
alias define_default_types register_default_types
|
286
296
|
|
287
|
-
|
288
|
-
|
289
|
-
%i[ register_coder register_type alias_type ].each do |meth|
|
290
|
-
define_method(meth) do |*args|
|
291
|
-
warn "PG::BasicTypeRegistry.#{meth} is deprecated. Please use your own instance by PG::BasicTypeRegistry.new instead!"
|
292
|
-
DEFAULT_TYPE_REGISTRY.send(meth, *args)
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
297
|
+
DEFAULT_TYPE_REGISTRY = PG.make_shareable(PG::BasicTypeRegistry.new.register_default_types)
|
298
|
+
private_constant :DEFAULT_TYPE_REGISTRY
|
296
299
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module PG
|
5
|
+
module BinaryDecoder
|
6
|
+
# Convenience classes for timezone options
|
7
|
+
class TimestampUtc < Timestamp
|
8
|
+
def initialize(hash={}, **kwargs)
|
9
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) unless hash.empty?
|
10
|
+
super(**hash, **kwargs, flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_UTC)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class TimestampUtcToLocal < Timestamp
|
14
|
+
def initialize(hash={}, **kwargs)
|
15
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) unless hash.empty?
|
16
|
+
super(**hash, **kwargs, flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
class TimestampLocal < Timestamp
|
20
|
+
def initialize(hash={}, **kwargs)
|
21
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) unless hash.empty?
|
22
|
+
super(**hash, **kwargs, flags: PG::Coder::TIMESTAMP_DB_LOCAL | PG::Coder::TIMESTAMP_APP_LOCAL)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end # module PG
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module PG
|
5
|
+
module BinaryEncoder
|
6
|
+
# Convenience classes for timezone options
|
7
|
+
class TimestampUtc < Timestamp
|
8
|
+
def initialize(hash={}, **kwargs)
|
9
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) unless hash.empty?
|
10
|
+
super(**hash, **kwargs, flags: PG::Coder::TIMESTAMP_DB_UTC)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class TimestampLocal < Timestamp
|
14
|
+
def initialize(hash={}, **kwargs)
|
15
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) unless hash.empty?
|
16
|
+
super(**hash, **kwargs, flags: PG::Coder::TIMESTAMP_DB_LOCAL)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end # module PG
|
data/lib/pg/coder.rb
CHANGED
@@ -6,22 +6,24 @@ module PG
|
|
6
6
|
class Coder
|
7
7
|
|
8
8
|
module BinaryFormatting
|
9
|
-
|
10
|
-
|
11
|
-
super(
|
9
|
+
def initialize(hash={}, **kwargs)
|
10
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) unless hash.empty?
|
11
|
+
super(format: 1, **hash, **kwargs)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
|
16
16
|
# Create a new coder object based on the attribute Hash.
|
17
|
-
def initialize(
|
18
|
-
|
17
|
+
def initialize(hash=nil, **kwargs)
|
18
|
+
warn("PG::Coder.new(hash) is deprecated. Please use keyword arguments instead! Called from #{caller.first}", category: :deprecated) if hash
|
19
|
+
|
20
|
+
(hash || kwargs).each do |key, val|
|
19
21
|
send("#{key}=", val)
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
def dup
|
24
|
-
self.class.new(to_h)
|
26
|
+
self.class.new(**to_h)
|
25
27
|
end
|
26
28
|
|
27
29
|
# Returns coder attributes as Hash.
|
@@ -43,7 +45,7 @@ module PG
|
|
43
45
|
end
|
44
46
|
|
45
47
|
def marshal_load(str)
|
46
|
-
initialize
|
48
|
+
initialize(**Marshal.load(str))
|
47
49
|
end
|
48
50
|
|
49
51
|
def inspect
|
@@ -70,11 +72,11 @@ module PG
|
|
70
72
|
|
71
73
|
class CompositeCoder < Coder
|
72
74
|
def to_h
|
73
|
-
super
|
75
|
+
{ **super,
|
74
76
|
elements_type: elements_type,
|
75
77
|
needs_quotation: needs_quotation?,
|
76
78
|
delimiter: delimiter,
|
77
|
-
}
|
79
|
+
}
|
78
80
|
end
|
79
81
|
|
80
82
|
def inspect
|
@@ -86,19 +88,19 @@ module PG
|
|
86
88
|
|
87
89
|
class CopyCoder < Coder
|
88
90
|
def to_h
|
89
|
-
super
|
91
|
+
{ **super,
|
90
92
|
type_map: type_map,
|
91
93
|
delimiter: delimiter,
|
92
94
|
null_string: null_string,
|
93
|
-
}
|
95
|
+
}
|
94
96
|
end
|
95
97
|
end
|
96
98
|
|
97
99
|
class RecordCoder < Coder
|
98
100
|
def to_h
|
99
|
-
super
|
101
|
+
{ **super,
|
100
102
|
type_map: type_map,
|
101
|
-
}
|
103
|
+
}
|
102
104
|
end
|
103
105
|
end
|
104
106
|
end # module PG
|