cipherstash-pg 1.0.0.beta.1-x86_64-linux → 1.0.0.beta.4-x86_64-linux

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +4 -4
  2. data/.appveyor.yml +42 -0
  3. data/.gems +6 -0
  4. data/.gemtest +0 -0
  5. data/.github/workflows/binary-gems.yml +117 -0
  6. data/.github/workflows/source-gem.yml +137 -0
  7. data/.gitignore +19 -0
  8. data/.hgsigs +34 -0
  9. data/.hgtags +41 -0
  10. data/.irbrc +23 -0
  11. data/.pryrc +23 -0
  12. data/.tm_properties +21 -0
  13. data/.travis.yml +49 -0
  14. data/Gemfile +3 -3
  15. data/Gemfile.lock +45 -0
  16. data/{History.rdoc → History.md} +168 -153
  17. data/README.ja.md +266 -0
  18. data/README.md +272 -0
  19. data/Rakefile +65 -104
  20. data/Rakefile.cross +298 -0
  21. data/certs/larskanis-2023.pem +24 -0
  22. data/cipherstash-pg.gemspec +0 -0
  23. data/lib/2.7/pg_ext.so +0 -0
  24. data/lib/3.0/pg_ext.so +0 -0
  25. data/lib/3.1/pg_ext.so +0 -0
  26. data/lib/3.2/pg_ext.so +0 -0
  27. data/lib/cipherstash-pg/basic_type_map_based_on_result.rb +11 -0
  28. data/lib/cipherstash-pg/basic_type_map_for_queries.rb +113 -0
  29. data/lib/cipherstash-pg/basic_type_map_for_results.rb +30 -0
  30. data/lib/cipherstash-pg/basic_type_registry.rb +206 -0
  31. data/lib/cipherstash-pg/binary_decoder.rb +21 -0
  32. data/lib/cipherstash-pg/coder.rb +82 -0
  33. data/lib/cipherstash-pg/connection.rb +467 -0
  34. data/lib/cipherstash-pg/constants.rb +3 -0
  35. data/lib/cipherstash-pg/exceptions.rb +19 -0
  36. data/lib/cipherstash-pg/result.rb +22 -0
  37. data/lib/cipherstash-pg/text_decoder.rb +43 -0
  38. data/lib/cipherstash-pg/text_encoder.rb +67 -0
  39. data/lib/cipherstash-pg/tuple.rb +24 -0
  40. data/lib/cipherstash-pg/type_map_by_column.rb +11 -0
  41. data/lib/cipherstash-pg/version.rb +3 -0
  42. data/lib/cipherstash-pg.rb +56 -11
  43. data/lib/libpq.so.5 +0 -0
  44. data/misc/openssl-pg-segfault.rb +15 -25
  45. data/misc/postgres/Rakefile +13 -20
  46. data/misc/postgres/lib/postgres.rb +10 -14
  47. data/misc/ruby-pg/Rakefile +13 -20
  48. data/misc/ruby-pg/lib/ruby/pg.rb +10 -14
  49. data/rakelib/task_extension.rb +17 -31
  50. data/sample/array_insert.rb +7 -20
  51. data/sample/async_api.rb +54 -96
  52. data/sample/async_copyto.rb +20 -35
  53. data/sample/async_mixed.rb +22 -50
  54. data/sample/check_conn.rb +8 -20
  55. data/sample/copydata.rb +18 -68
  56. data/sample/copyfrom.rb +26 -78
  57. data/sample/copyto.rb +10 -16
  58. data/sample/cursor.rb +9 -19
  59. data/sample/disk_usage_report.rb +89 -174
  60. data/sample/issue-119.rb +45 -93
  61. data/sample/losample.rb +48 -66
  62. data/sample/minimal-testcase.rb +6 -17
  63. data/sample/notify_wait.rb +21 -67
  64. data/sample/pg_statistics.rb +100 -281
  65. data/sample/replication_monitor.rb +119 -218
  66. data/sample/test_binary_values.rb +14 -30
  67. data/sample/wal_shipper.rb +199 -431
  68. data/sample/warehouse_partitions.rb +157 -307
  69. data/translation/.po4a-version +7 -0
  70. data/translation/po/all.pot +875 -0
  71. data/translation/po/ja.po +868 -0
  72. data/translation/po4a.cfg +9 -0
  73. metadata +50 -28
  74. data/README.ja.rdoc +0 -13
  75. data/README.rdoc +0 -233
  76. data/lib/pg/basic_type_map_based_on_result.rb +0 -47
  77. data/lib/pg/basic_type_map_for_queries.rb +0 -193
  78. data/lib/pg/basic_type_map_for_results.rb +0 -81
  79. data/lib/pg/basic_type_registry.rb +0 -301
  80. data/lib/pg/binary_decoder.rb +0 -23
  81. data/lib/pg/coder.rb +0 -104
  82. data/lib/pg/connection.rb +0 -878
  83. data/lib/pg/constants.rb +0 -12
  84. data/lib/pg/exceptions.rb +0 -18
  85. data/lib/pg/result.rb +0 -43
  86. data/lib/pg/text_decoder.rb +0 -46
  87. data/lib/pg/text_encoder.rb +0 -59
  88. data/lib/pg/tuple.rb +0 -30
  89. data/lib/pg/type_map_by_column.rb +0 -16
  90. data/lib/pg/version.rb +0 -4
  91. data/lib/pg.rb +0 -55
@@ -1,81 +0,0 @@
1
- # -*- ruby -*-
2
- # frozen_string_literal: true
3
-
4
- require 'pg' unless defined?( PG )
5
-
6
- # Simple set of rules for type casting common PostgreSQL types to Ruby.
7
- #
8
- # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
9
- # PostgreSQL's +pg_type+ table in PG::BasicTypeMapForResults.new .
10
- #
11
- # Result values are type casted based on the type OID of the given result column.
12
- #
13
- # Higher level libraries will most likely not make use of this class, but use their
14
- # own set of rules to choose suitable encoders and decoders.
15
- #
16
- # Example:
17
- # conn = PG::Connection.new
18
- # # Assign a default ruleset for type casts of output values.
19
- # conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
20
- # # Execute a query.
21
- # res = conn.exec_params( "SELECT $1::INT", ['5'] )
22
- # # Retrieve and cast the result value. Value format is 0 (text) and OID is 20. Therefore typecasting
23
- # # is done by PG::TextDecoder::Integer internally for all value retrieval methods.
24
- # res.values # => [[5]]
25
- #
26
- # PG::TypeMapByOid#build_column_map(result) can be used to generate
27
- # a result independent PG::TypeMapByColumn type map, which can subsequently be used
28
- # to cast #get_copy_data fields:
29
- #
30
- # For the following table:
31
- # conn.exec( "CREATE TABLE copytable AS VALUES('a', 123, '{5,4,3}'::INT[])" )
32
- #
33
- # # Retrieve table OIDs per empty result set.
34
- # res = conn.exec( "SELECT * FROM copytable LIMIT 0" )
35
- # # Build a type map for common database to ruby type decoders.
36
- # btm = PG::BasicTypeMapForResults.new(conn)
37
- # # Build a PG::TypeMapByColumn with decoders suitable for copytable.
38
- # tm = btm.build_column_map( res )
39
- # row_decoder = PG::TextDecoder::CopyRow.new type_map: tm
40
- #
41
- # conn.copy_data( "COPY copytable TO STDOUT", row_decoder ) do |res|
42
- # while row=conn.get_copy_data
43
- # p row
44
- # end
45
- # end
46
- # This prints the rows with type casted columns:
47
- # ["a", 123, [5, 4, 3]]
48
- #
49
- # See also PG::BasicTypeMapBasedOnResult for the encoder direction and PG::BasicTypeRegistry for the definition of additional types.
50
- class PG::BasicTypeMapForResults < PG::TypeMapByOid
51
- include PG::BasicTypeRegistry::Checker
52
-
53
- class WarningTypeMap < PG::TypeMapInRuby
54
- def initialize(typenames)
55
- @already_warned = Hash.new{|h, k| h[k] = {} }
56
- @typenames_by_oid = typenames
57
- end
58
-
59
- def typecast_result_value(result, _tuple, field)
60
- format = result.fformat(field)
61
- oid = result.ftype(field)
62
- unless @already_warned[format][oid]
63
- warn "Warning: no type cast defined for type #{@typenames_by_oid[oid].inspect} format #{format} with oid #{oid}. Please cast this type explicitly to TEXT to be safe for future changes."
64
- @already_warned[format][oid] = true
65
- end
66
- super
67
- end
68
- end
69
-
70
- def initialize(connection_or_coder_maps, registry: nil)
71
- @coder_maps = build_coder_maps(connection_or_coder_maps, registry: registry)
72
-
73
- # Populate TypeMapByOid hash with decoders
74
- @coder_maps.each_format(:decoder).flat_map{|f| f.coders }.each do |coder|
75
- add_coder(coder)
76
- end
77
-
78
- typenames = @coder_maps.typenames_by_oid
79
- self.default_type_map = WarningTypeMap.new(typenames)
80
- end
81
- end
@@ -1,301 +0,0 @@
1
- # -*- ruby -*-
2
- # frozen_string_literal: true
3
-
4
- require 'pg' unless defined?( PG )
5
-
6
- # This class defines the mapping between PostgreSQL types and encoder/decoder classes for PG::BasicTypeMapForResults, PG::BasicTypeMapForQueries and PG::BasicTypeMapBasedOnResult.
7
- #
8
- # Additional types can be added like so:
9
- #
10
- # require 'pg'
11
- # require 'ipaddr'
12
- #
13
- # class InetDecoder < PG::SimpleDecoder
14
- # def decode(string, tuple=nil, field=nil)
15
- # IPAddr.new(string)
16
- # end
17
- # end
18
- # class InetEncoder < PG::SimpleEncoder
19
- # def encode(ip_addr)
20
- # ip_addr.to_s
21
- # end
22
- # end
23
- #
24
- # conn = PG.connect
25
- # regi = PG::BasicTypeRegistry.new.register_default_types
26
- # regi.register_type(0, 'inet', InetEncoder, InetDecoder)
27
- # conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn, registry: regi)
28
- class PG::BasicTypeRegistry
29
- # An instance of this class stores the coders that should be used for a particular wire format (text or binary)
30
- # and type cast direction (encoder or decoder).
31
- #
32
- # Each coder object is filled with the PostgreSQL type name, OID, wire format and array coders are filled with the base elements_type.
33
- class CoderMap
34
- # Hash of text types that don't require quotation, when used within composite types.
35
- # type.name => true
36
- DONT_QUOTE_TYPES = %w[
37
- int2 int4 int8
38
- float4 float8
39
- oid
40
- bool
41
- date timestamp timestamptz
42
- ].inject({}){|h,e| h[e] = true; h }
43
-
44
- def initialize(result, coders_by_name, format, arraycoder)
45
- coder_map = {}
46
-
47
- arrays, nodes = result.partition { |row| row['typinput'] == 'array_in' }
48
-
49
- # populate the base types
50
- nodes.find_all { |row| coders_by_name.key?(row['typname']) }.each do |row|
51
- coder = coders_by_name[row['typname']].dup
52
- coder.oid = row['oid'].to_i
53
- coder.name = row['typname']
54
- coder.format = format
55
- coder_map[coder.oid] = coder
56
- end
57
-
58
- if arraycoder
59
- # populate array types
60
- arrays.each do |row|
61
- elements_coder = coder_map[row['typelem'].to_i]
62
- next unless elements_coder
63
-
64
- coder = arraycoder.new
65
- coder.oid = row['oid'].to_i
66
- coder.name = row['typname']
67
- coder.format = format
68
- coder.elements_type = elements_coder
69
- coder.needs_quotation = !DONT_QUOTE_TYPES[elements_coder.name]
70
- coder_map[coder.oid] = coder
71
- end
72
- end
73
-
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 }
77
- end
78
-
79
- attr_reader :coders
80
- attr_reader :coders_by_oid
81
- attr_reader :coders_by_name
82
-
83
- def coder_by_name(name)
84
- @coders_by_name[name]
85
- end
86
-
87
- def coder_by_oid(oid)
88
- @coders_by_oid[oid]
89
- end
90
- end
91
-
92
- # An instance of this class stores CoderMap instances to be used for text and binary wire formats
93
- # as well as encoder and decoder directions.
94
- #
95
- # A PG::BasicTypeRegistry::CoderMapsBundle instance retrieves all type definitions from the PostgreSQL server and matches them with the coder definitions of the global PG::BasicTypeRegistry .
96
- # It provides 4 separate CoderMap instances for the combinations of the two formats and directions.
97
- #
98
- # A PG::BasicTypeRegistry::CoderMapsBundle instance can be used to initialize an instance of
99
- # * PG::BasicTypeMapForResults
100
- # * PG::BasicTypeMapForQueries
101
- # * PG::BasicTypeMapBasedOnResult
102
- # by passing it instead of the connection object like so:
103
- #
104
- # conn = PG::Connection.new
105
- # maps = PG::BasicTypeRegistry::CoderMapsBundle.new(conn)
106
- # conn.type_map_for_results = PG::BasicTypeMapForResults.new(maps)
107
- #
108
- class CoderMapsBundle
109
- attr_reader :typenames_by_oid
110
-
111
- def initialize(connection, registry: nil)
112
- registry ||= DEFAULT_TYPE_REGISTRY
113
-
114
- result = connection.exec(<<-SQL).to_a
115
- SELECT t.oid, t.typname, t.typelem, t.typdelim, ti.proname AS typinput
116
- FROM pg_type as t
117
- JOIN pg_proc as ti ON ti.oid = t.typinput
118
- SQL
119
-
120
- @maps = [
121
- [0, :encoder, PG::TextEncoder::Array],
122
- [0, :decoder, PG::TextDecoder::Array],
123
- [1, :encoder, nil],
124
- [1, :decoder, nil],
125
- ].inject([]) do |h, (format, direction, arraycoder)|
126
- coders = registry.coders_for(format, direction) || {}
127
- h[format] ||= {}
128
- h[format][direction] = CoderMap.new(result, coders, format, arraycoder)
129
- h
130
- end
131
-
132
- @typenames_by_oid = result.inject({}){|h, t| h[t['oid'].to_i] = t['typname']; h }
133
- end
134
-
135
- def each_format(direction)
136
- @maps.map { |f| f[direction] }
137
- end
138
-
139
- def map_for(format, direction)
140
- @maps[format][direction]
141
- end
142
- end
143
-
144
- module Checker
145
- ValidFormats = { 0 => true, 1 => true }
146
- ValidDirections = { :encoder => true, :decoder => true }
147
-
148
- protected def check_format_and_direction(format, direction)
149
- raise(ArgumentError, "Invalid format value %p" % format) unless ValidFormats[format]
150
- raise(ArgumentError, "Invalid direction %p" % direction) unless ValidDirections[direction]
151
- end
152
-
153
- protected def build_coder_maps(conn_or_maps, registry: nil)
154
- if conn_or_maps.is_a?(PG::BasicTypeRegistry::CoderMapsBundle)
155
- raise ArgumentError, "registry argument must be given to CoderMapsBundle" if registry
156
- conn_or_maps
157
- else
158
- PG::BasicTypeRegistry::CoderMapsBundle.new(conn_or_maps, registry: registry)
159
- end
160
- end
161
- end
162
-
163
- include Checker
164
-
165
- def initialize
166
- # The key of these hashs maps to the `typname` column from the table pg_type.
167
- @coders_by_name = []
168
- end
169
-
170
- # Retrieve a Hash of all en- or decoders for a given wire format.
171
- # The hash key is the name as defined in table +pg_type+.
172
- # The hash value is the registered coder object.
173
- def coders_for(format, direction)
174
- check_format_and_direction(format, direction)
175
- @coders_by_name[format]&.[](direction)
176
- end
177
-
178
- # Register an encoder or decoder instance for casting a PostgreSQL type.
179
- #
180
- # Coder#name must correspond to the +typname+ column in the +pg_type+ table.
181
- # Coder#format can be 0 for text format and 1 for binary.
182
- def register_coder(coder)
183
- h = @coders_by_name[coder.format] ||= { encoder: {}, decoder: {} }
184
- name = coder.name || raise(ArgumentError, "name of #{coder.inspect} must be defined")
185
- h[:encoder][name] = coder if coder.respond_to?(:encode)
186
- h[:decoder][name] = coder if coder.respond_to?(:decode)
187
- self
188
- end
189
-
190
- # Register the given +encoder_class+ and/or +decoder_class+ for casting a PostgreSQL type.
191
- #
192
- # +name+ must correspond to the +typname+ column in the +pg_type+ table.
193
- # +format+ can be 0 for text format and 1 for binary.
194
- def register_type(format, name, encoder_class, decoder_class)
195
- register_coder(encoder_class.new(name: name, format: format)) if encoder_class
196
- register_coder(decoder_class.new(name: name, format: format)) if decoder_class
197
- self
198
- end
199
-
200
- # Alias the +old+ type to the +new+ type.
201
- def alias_type(format, new, old)
202
- [:encoder, :decoder].each do |ende|
203
- enc = @coders_by_name[format][ende][old]
204
- if enc
205
- @coders_by_name[format][ende][new] = enc
206
- else
207
- @coders_by_name[format][ende].delete(new)
208
- end
209
- end
210
- self
211
- end
212
-
213
- # Populate the registry with all builtin types of ruby-pg
214
- def register_default_types
215
- register_type 0, 'int2', PG::TextEncoder::Integer, PG::TextDecoder::Integer
216
- alias_type 0, 'int4', 'int2'
217
- alias_type 0, 'int8', 'int2'
218
- alias_type 0, 'oid', 'int2'
219
-
220
- register_type 0, 'numeric', PG::TextEncoder::Numeric, PG::TextDecoder::Numeric
221
- register_type 0, 'text', PG::TextEncoder::String, PG::TextDecoder::String
222
- alias_type 0, 'varchar', 'text'
223
- alias_type 0, 'char', 'text'
224
- alias_type 0, 'bpchar', 'text'
225
- alias_type 0, 'xml', 'text'
226
- alias_type 0, 'name', 'text'
227
-
228
- # FIXME: why are we keeping these types as strings?
229
- # alias_type 'tsvector', 'text'
230
- # alias_type 'interval', 'text'
231
- # alias_type 'macaddr', 'text'
232
- # alias_type 'uuid', 'text'
233
- #
234
- # register_type 'money', OID::Money.new
235
- # There is no PG::TextEncoder::Bytea, because it's simple and more efficient to send bytea-data
236
- # in binary format, either with PG::BinaryEncoder::Bytea or in Hash param format.
237
- register_type 0, 'bytea', nil, PG::TextDecoder::Bytea
238
- register_type 0, 'bool', PG::TextEncoder::Boolean, PG::TextDecoder::Boolean
239
- # register_type 'bit', OID::Bit.new
240
- # register_type 'varbit', OID::Bit.new
241
-
242
- register_type 0, 'float4', PG::TextEncoder::Float, PG::TextDecoder::Float
243
- alias_type 0, 'float8', 'float4'
244
-
245
- register_type 0, 'timestamp', PG::TextEncoder::TimestampWithoutTimeZone, PG::TextDecoder::TimestampWithoutTimeZone
246
- register_type 0, 'timestamptz', PG::TextEncoder::TimestampWithTimeZone, PG::TextDecoder::TimestampWithTimeZone
247
- register_type 0, 'date', PG::TextEncoder::Date, PG::TextDecoder::Date
248
- # register_type 'time', OID::Time.new
249
- #
250
- # register_type 'path', OID::Text.new
251
- # register_type 'point', OID::Point.new
252
- # register_type 'polygon', OID::Text.new
253
- # register_type 'circle', OID::Text.new
254
- # register_type 'hstore', OID::Hstore.new
255
- register_type 0, 'json', PG::TextEncoder::JSON, PG::TextDecoder::JSON
256
- alias_type 0, 'jsonb', 'json'
257
- # register_type 'citext', OID::Text.new
258
- # register_type 'ltree', OID::Text.new
259
- #
260
- register_type 0, 'inet', PG::TextEncoder::Inet, PG::TextDecoder::Inet
261
- alias_type 0, 'cidr', 'inet'
262
-
263
-
264
-
265
- register_type 1, 'int2', PG::BinaryEncoder::Int2, PG::BinaryDecoder::Integer
266
- register_type 1, 'int4', PG::BinaryEncoder::Int4, PG::BinaryDecoder::Integer
267
- register_type 1, 'int8', PG::BinaryEncoder::Int8, PG::BinaryDecoder::Integer
268
- alias_type 1, 'oid', 'int2'
269
-
270
- register_type 1, 'text', PG::BinaryEncoder::String, PG::BinaryDecoder::String
271
- alias_type 1, 'varchar', 'text'
272
- alias_type 1, 'char', 'text'
273
- alias_type 1, 'bpchar', 'text'
274
- alias_type 1, 'xml', 'text'
275
- alias_type 1, 'name', 'text'
276
-
277
- register_type 1, 'bytea', PG::BinaryEncoder::Bytea, PG::BinaryDecoder::Bytea
278
- register_type 1, 'bool', PG::BinaryEncoder::Boolean, PG::BinaryDecoder::Boolean
279
- register_type 1, 'float4', nil, PG::BinaryDecoder::Float
280
- register_type 1, 'float8', nil, PG::BinaryDecoder::Float
281
- register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampUtc
282
- register_type 1, 'timestamptz', nil, PG::BinaryDecoder::TimestampUtcToLocal
283
-
284
- self
285
- end
286
-
287
- alias define_default_types register_default_types
288
-
289
- # @private
290
- DEFAULT_TYPE_REGISTRY = PG::BasicTypeRegistry.new.register_default_types
291
-
292
- # Delegate class method calls to DEFAULT_TYPE_REGISTRY
293
- class << self
294
- %i[ register_coder register_type alias_type ].each do |meth|
295
- define_method(meth) do |*args|
296
- warn "PG::BasicTypeRegistry.#{meth} is deprecated. Please use your own instance by PG::BasicTypeRegistry.new instead!"
297
- DEFAULT_TYPE_REGISTRY.send(meth, *args)
298
- end
299
- end
300
- end
301
- end
@@ -1,23 +0,0 @@
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(params={})
9
- super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_UTC))
10
- end
11
- end
12
- class TimestampUtcToLocal < Timestamp
13
- def initialize(params={})
14
- super(params.merge(flags: PG::Coder::TIMESTAMP_DB_UTC | PG::Coder::TIMESTAMP_APP_LOCAL))
15
- end
16
- end
17
- class TimestampLocal < Timestamp
18
- def initialize(params={})
19
- super(params.merge(flags: PG::Coder::TIMESTAMP_DB_LOCAL | PG::Coder::TIMESTAMP_APP_LOCAL))
20
- end
21
- end
22
- end
23
- end # module PG
data/lib/pg/coder.rb DELETED
@@ -1,104 +0,0 @@
1
- # -*- ruby -*-
2
- # frozen_string_literal: true
3
-
4
- module PG
5
-
6
- class Coder
7
-
8
- module BinaryFormatting
9
- Params = { format: 1 }
10
- def initialize( params={} )
11
- super(Params.merge(params))
12
- end
13
- end
14
-
15
-
16
- # Create a new coder object based on the attribute Hash.
17
- def initialize(params={})
18
- params.each do |key, val|
19
- send("#{key}=", val)
20
- end
21
- end
22
-
23
- def dup
24
- self.class.new(to_h)
25
- end
26
-
27
- # Returns coder attributes as Hash.
28
- def to_h
29
- {
30
- oid: oid,
31
- format: format,
32
- flags: flags,
33
- name: name,
34
- }
35
- end
36
-
37
- def ==(v)
38
- self.class == v.class && to_h == v.to_h
39
- end
40
-
41
- def marshal_dump
42
- Marshal.dump(to_h)
43
- end
44
-
45
- def marshal_load(str)
46
- initialize Marshal.load(str)
47
- end
48
-
49
- def inspect
50
- str = self.to_s
51
- oid_str = " oid=#{oid}" unless oid==0
52
- format_str = " format=#{format}" unless format==0
53
- name_str = " #{name.inspect}" if name
54
- str[-1,0] = "#{name_str} #{oid_str}#{format_str}"
55
- str
56
- end
57
-
58
- def inspect_short
59
- str = case format
60
- when 0 then "T"
61
- when 1 then "B"
62
- else format.to_s
63
- end
64
- str += "E" if respond_to?(:encode)
65
- str += "D" if respond_to?(:decode)
66
-
67
- "#{name || self.class.name}:#{str}"
68
- end
69
- end
70
-
71
- class CompositeCoder < Coder
72
- def to_h
73
- super.merge!({
74
- elements_type: elements_type,
75
- needs_quotation: needs_quotation?,
76
- delimiter: delimiter,
77
- })
78
- end
79
-
80
- def inspect
81
- str = super
82
- str[-1,0] = " elements_type=#{elements_type.inspect} #{needs_quotation? ? 'needs' : 'no'} quotation"
83
- str
84
- end
85
- end
86
-
87
- class CopyCoder < Coder
88
- def to_h
89
- super.merge!({
90
- type_map: type_map,
91
- delimiter: delimiter,
92
- null_string: null_string,
93
- })
94
- end
95
- end
96
-
97
- class RecordCoder < Coder
98
- def to_h
99
- super.merge!({
100
- type_map: type_map,
101
- })
102
- end
103
- end
104
- end # module PG