pg 1.2.3-x86-mingw32 → 1.3.0.rc4-x86-mingw32

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 (112) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.appveyor.yml +36 -0
  4. data/.gems +6 -0
  5. data/.github/workflows/binary-gems.yml +86 -0
  6. data/.github/workflows/source-gem.yml +130 -0
  7. data/.gitignore +13 -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 +14 -0
  15. data/History.rdoc +77 -7
  16. data/Manifest.txt +0 -1
  17. data/README.rdoc +7 -6
  18. data/Rakefile +27 -138
  19. data/Rakefile.cross +6 -5
  20. data/certs/ged.pem +24 -0
  21. data/ext/errorcodes.def +8 -0
  22. data/ext/errorcodes.txt +3 -1
  23. data/ext/extconf.rb +91 -19
  24. data/ext/gvl_wrappers.c +4 -0
  25. data/ext/gvl_wrappers.h +23 -0
  26. data/ext/pg.c +59 -4
  27. data/ext/pg.h +18 -1
  28. data/ext/pg_coder.c +82 -28
  29. data/ext/pg_connection.c +676 -492
  30. data/ext/pg_copy_coder.c +45 -16
  31. data/ext/pg_record_coder.c +39 -11
  32. data/ext/pg_result.c +61 -31
  33. data/ext/pg_text_decoder.c +1 -1
  34. data/ext/pg_text_encoder.c +6 -6
  35. data/ext/pg_tuple.c +47 -21
  36. data/ext/pg_type_map.c +41 -8
  37. data/ext/pg_type_map_all_strings.c +14 -1
  38. data/ext/pg_type_map_by_class.c +49 -24
  39. data/ext/pg_type_map_by_column.c +64 -28
  40. data/ext/pg_type_map_by_mri_type.c +47 -18
  41. data/ext/pg_type_map_by_oid.c +52 -23
  42. data/ext/pg_type_map_in_ruby.c +50 -19
  43. data/ext/pg_util.c +2 -2
  44. data/lib/2.5/pg_ext.so +0 -0
  45. data/lib/2.6/pg_ext.so +0 -0
  46. data/lib/2.7/pg_ext.so +0 -0
  47. data/lib/3.0/pg_ext.so +0 -0
  48. data/lib/3.1/pg_ext.so +0 -0
  49. data/lib/pg/basic_type_map_based_on_result.rb +47 -0
  50. data/lib/pg/basic_type_map_for_queries.rb +193 -0
  51. data/lib/pg/basic_type_map_for_results.rb +81 -0
  52. data/lib/pg/basic_type_registry.rb +296 -0
  53. data/lib/pg/coder.rb +1 -1
  54. data/lib/pg/connection.rb +587 -58
  55. data/lib/pg/version.rb +4 -0
  56. data/lib/pg.rb +40 -27
  57. data/lib/x86-mingw32/libpq.dll +0 -0
  58. data/misc/openssl-pg-segfault.rb +31 -0
  59. data/misc/postgres/History.txt +9 -0
  60. data/misc/postgres/Manifest.txt +5 -0
  61. data/misc/postgres/README.txt +21 -0
  62. data/misc/postgres/Rakefile +21 -0
  63. data/misc/postgres/lib/postgres.rb +16 -0
  64. data/misc/ruby-pg/History.txt +9 -0
  65. data/misc/ruby-pg/Manifest.txt +5 -0
  66. data/misc/ruby-pg/README.txt +21 -0
  67. data/misc/ruby-pg/Rakefile +21 -0
  68. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  69. data/pg.gemspec +32 -0
  70. data/sample/array_insert.rb +20 -0
  71. data/sample/async_api.rb +106 -0
  72. data/sample/async_copyto.rb +39 -0
  73. data/sample/async_mixed.rb +56 -0
  74. data/sample/check_conn.rb +21 -0
  75. data/sample/copydata.rb +71 -0
  76. data/sample/copyfrom.rb +81 -0
  77. data/sample/copyto.rb +19 -0
  78. data/sample/cursor.rb +21 -0
  79. data/sample/disk_usage_report.rb +177 -0
  80. data/sample/issue-119.rb +94 -0
  81. data/sample/losample.rb +69 -0
  82. data/sample/minimal-testcase.rb +17 -0
  83. data/sample/notify_wait.rb +72 -0
  84. data/sample/pg_statistics.rb +285 -0
  85. data/sample/replication_monitor.rb +222 -0
  86. data/sample/test_binary_values.rb +33 -0
  87. data/sample/wal_shipper.rb +434 -0
  88. data/sample/warehouse_partitions.rb +311 -0
  89. data.tar.gz.sig +0 -0
  90. metadata +93 -233
  91. metadata.gz.sig +0 -0
  92. data/ChangeLog +0 -0
  93. data/lib/2.2/pg_ext.so +0 -0
  94. data/lib/2.3/pg_ext.so +0 -0
  95. data/lib/2.4/pg_ext.so +0 -0
  96. data/lib/pg/basic_type_mapping.rb +0 -522
  97. data/spec/data/expected_trace.out +0 -26
  98. data/spec/data/random_binary_data +0 -0
  99. data/spec/helpers.rb +0 -380
  100. data/spec/pg/basic_type_mapping_spec.rb +0 -630
  101. data/spec/pg/connection_spec.rb +0 -1949
  102. data/spec/pg/connection_sync_spec.rb +0 -41
  103. data/spec/pg/result_spec.rb +0 -681
  104. data/spec/pg/tuple_spec.rb +0 -333
  105. data/spec/pg/type_map_by_class_spec.rb +0 -138
  106. data/spec/pg/type_map_by_column_spec.rb +0 -226
  107. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  108. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  109. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  110. data/spec/pg/type_map_spec.rb +0 -22
  111. data/spec/pg/type_spec.rb +0 -1123
  112. data/spec/pg_spec.rb +0 -50
data/ChangeLog DELETED
File without changes
data/lib/2.2/pg_ext.so DELETED
Binary file
data/lib/2.3/pg_ext.so DELETED
Binary file
data/lib/2.4/pg_ext.so DELETED
Binary file
@@ -1,522 +0,0 @@
1
- # -*- ruby -*-
2
- # frozen_string_literal: true
3
-
4
- require 'pg' unless defined?( PG )
5
-
6
- # This module defines the mapping between OID 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
- # # 0 if for text format, can also be 1 for binary
25
- # PG::BasicTypeRegistry.register_type(0, 'inet', InetEncoder, InetDecoder)
26
- module PG::BasicTypeRegistry
27
- # An instance of this class stores the coders that should be used for a given wire format (text or binary)
28
- # and type cast direction (encoder or decoder).
29
- class CoderMap
30
- # Hash of text types that don't require quotation, when used within composite types.
31
- # type.name => true
32
- DONT_QUOTE_TYPES = %w[
33
- int2 int4 int8
34
- float4 float8
35
- oid
36
- bool
37
- date timestamp timestamptz
38
- ].inject({}){|h,e| h[e] = true; h }
39
-
40
- def initialize(result, coders_by_name, format, arraycoder)
41
- coder_map = {}
42
-
43
- _ranges, nodes = result.partition { |row| row['typinput'] == 'range_in' }
44
- leaves, nodes = nodes.partition { |row| row['typelem'].to_i == 0 }
45
- arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' }
46
-
47
- # populate the enum types
48
- _enums, leaves = leaves.partition { |row| row['typinput'] == 'enum_in' }
49
- # enums.each do |row|
50
- # coder_map[row['oid'].to_i] = OID::Enum.new
51
- # end
52
-
53
- # populate the base types
54
- leaves.find_all { |row| coders_by_name.key?(row['typname']) }.each do |row|
55
- coder = coders_by_name[row['typname']].dup
56
- coder.oid = row['oid'].to_i
57
- coder.name = row['typname']
58
- coder.format = format
59
- coder_map[coder.oid] = coder
60
- end
61
-
62
- _records_by_oid = result.group_by { |row| row['oid'] }
63
-
64
- # populate composite types
65
- # nodes.each do |row|
66
- # add_oid row, records_by_oid, coder_map
67
- # end
68
-
69
- if arraycoder
70
- # populate array types
71
- arrays.each do |row|
72
- elements_coder = coder_map[row['typelem'].to_i]
73
- next unless elements_coder
74
-
75
- coder = arraycoder.new
76
- coder.oid = row['oid'].to_i
77
- coder.name = row['typname']
78
- coder.format = format
79
- coder.elements_type = elements_coder
80
- coder.needs_quotation = !DONT_QUOTE_TYPES[elements_coder.name]
81
- coder_map[coder.oid] = coder
82
- end
83
- end
84
-
85
- # populate range types
86
- # ranges.find_all { |row| coder_map.key? row['rngsubtype'].to_i }.each do |row|
87
- # subcoder = coder_map[row['rngsubtype'].to_i]
88
- # range = OID::Range.new subcoder
89
- # coder_map[row['oid'].to_i] = range
90
- # end
91
-
92
- @coders = coder_map.values
93
- @coders_by_name = @coders.inject({}){|h, t| h[t.name] = t; h }
94
- @coders_by_oid = @coders.inject({}){|h, t| h[t.oid] = t; h }
95
- @typenames_by_oid = result.inject({}){|h, t| h[t['oid'].to_i] = t['typname']; h }
96
- end
97
-
98
- attr_reader :coders
99
- attr_reader :coders_by_oid
100
- attr_reader :coders_by_name
101
- attr_reader :typenames_by_oid
102
-
103
- def coder_by_name(name)
104
- @coders_by_name[name]
105
- end
106
-
107
- def coder_by_oid(oid)
108
- @coders_by_oid[oid]
109
- end
110
- end
111
-
112
- private
113
-
114
- def supports_ranges?(connection)
115
- connection.server_version >= 90200
116
- end
117
-
118
- def build_coder_maps(connection)
119
- if supports_ranges?(connection)
120
- result = connection.exec <<-SQL
121
- SELECT t.oid, t.typname::text, t.typelem, t.typdelim, t.typinput::text, r.rngsubtype
122
- FROM pg_type as t
123
- LEFT JOIN pg_range as r ON oid = rngtypid
124
- SQL
125
- else
126
- result = connection.exec <<-SQL
127
- SELECT t.oid, t.typname::text, t.typelem, t.typdelim, t.typinput::text
128
- FROM pg_type as t
129
- SQL
130
- end
131
-
132
- [
133
- [0, :encoder, PG::TextEncoder::Array],
134
- [0, :decoder, PG::TextDecoder::Array],
135
- [1, :encoder, nil],
136
- [1, :decoder, nil],
137
- ].inject([]) do |h, (format, direction, arraycoder)|
138
- h[format] ||= {}
139
- h[format][direction] = CoderMap.new result, CODERS_BY_NAME[format][direction], format, arraycoder
140
- h
141
- end
142
- end
143
-
144
- ValidFormats = { 0 => true, 1 => true }
145
- ValidDirections = { :encoder => true, :decoder => true }
146
-
147
- def check_format_and_direction(format, direction)
148
- raise(ArgumentError, "Invalid format value %p" % format) unless ValidFormats[format]
149
- raise(ArgumentError, "Invalid direction %p" % direction) unless ValidDirections[direction]
150
- end
151
- protected :check_format_and_direction
152
-
153
- # The key of this hash maps to the `typname` column from the table.
154
- # encoder_map is then dynamically built with oids as the key and Type
155
- # objects as values.
156
- CODERS_BY_NAME = []
157
-
158
- public
159
-
160
- # Register an encoder or decoder instance for casting a PostgreSQL type.
161
- #
162
- # Coder#name must correspond to the +typname+ column in the +pg_type+ table.
163
- # Coder#format can be 0 for text format and 1 for binary.
164
- def self.register_coder(coder)
165
- h = CODERS_BY_NAME[coder.format] ||= { encoder: {}, decoder: {} }
166
- name = coder.name || raise(ArgumentError, "name of #{coder.inspect} must be defined")
167
- h[:encoder][name] = coder if coder.respond_to?(:encode)
168
- h[:decoder][name] = coder if coder.respond_to?(:decode)
169
- end
170
-
171
- # Register the given +encoder_class+ and/or +decoder_class+ for casting a PostgreSQL type.
172
- #
173
- # +name+ must correspond to the +typname+ column in the +pg_type+ table.
174
- # +format+ can be 0 for text format and 1 for binary.
175
- def self.register_type(format, name, encoder_class, decoder_class)
176
- register_coder(encoder_class.new(name: name, format: format)) if encoder_class
177
- register_coder(decoder_class.new(name: name, format: format)) if decoder_class
178
- end
179
-
180
- # Alias the +old+ type to the +new+ type.
181
- def self.alias_type(format, new, old)
182
- [:encoder, :decoder].each do |ende|
183
- enc = CODERS_BY_NAME[format][ende][old]
184
- if enc
185
- CODERS_BY_NAME[format][ende][new] = enc
186
- else
187
- CODERS_BY_NAME[format][ende].delete(new)
188
- end
189
- end
190
- end
191
-
192
- register_type 0, 'int2', PG::TextEncoder::Integer, PG::TextDecoder::Integer
193
- alias_type 0, 'int4', 'int2'
194
- alias_type 0, 'int8', 'int2'
195
- alias_type 0, 'oid', 'int2'
196
-
197
- register_type 0, 'numeric', PG::TextEncoder::Numeric, PG::TextDecoder::Numeric
198
- register_type 0, 'text', PG::TextEncoder::String, PG::TextDecoder::String
199
- alias_type 0, 'varchar', 'text'
200
- alias_type 0, 'char', 'text'
201
- alias_type 0, 'bpchar', 'text'
202
- alias_type 0, 'xml', 'text'
203
-
204
- # FIXME: why are we keeping these types as strings?
205
- # alias_type 'tsvector', 'text'
206
- # alias_type 'interval', 'text'
207
- # alias_type 'macaddr', 'text'
208
- # alias_type 'uuid', 'text'
209
- #
210
- # register_type 'money', OID::Money.new
211
- # There is no PG::TextEncoder::Bytea, because it's simple and more efficient to send bytea-data
212
- # in binary format, either with PG::BinaryEncoder::Bytea or in Hash param format.
213
- register_type 0, 'bytea', nil, PG::TextDecoder::Bytea
214
- register_type 0, 'bool', PG::TextEncoder::Boolean, PG::TextDecoder::Boolean
215
- # register_type 'bit', OID::Bit.new
216
- # register_type 'varbit', OID::Bit.new
217
-
218
- register_type 0, 'float4', PG::TextEncoder::Float, PG::TextDecoder::Float
219
- alias_type 0, 'float8', 'float4'
220
-
221
- register_type 0, 'timestamp', PG::TextEncoder::TimestampWithoutTimeZone, PG::TextDecoder::TimestampWithoutTimeZone
222
- register_type 0, 'timestamptz', PG::TextEncoder::TimestampWithTimeZone, PG::TextDecoder::TimestampWithTimeZone
223
- register_type 0, 'date', PG::TextEncoder::Date, PG::TextDecoder::Date
224
- # register_type 'time', OID::Time.new
225
- #
226
- # register_type 'path', OID::Text.new
227
- # register_type 'point', OID::Point.new
228
- # register_type 'polygon', OID::Text.new
229
- # register_type 'circle', OID::Text.new
230
- # register_type 'hstore', OID::Hstore.new
231
- register_type 0, 'json', PG::TextEncoder::JSON, PG::TextDecoder::JSON
232
- alias_type 0, 'jsonb', 'json'
233
- # register_type 'citext', OID::Text.new
234
- # register_type 'ltree', OID::Text.new
235
- #
236
- register_type 0, 'inet', PG::TextEncoder::Inet, PG::TextDecoder::Inet
237
- alias_type 0, 'cidr', 'inet'
238
-
239
-
240
-
241
- register_type 1, 'int2', PG::BinaryEncoder::Int2, PG::BinaryDecoder::Integer
242
- register_type 1, 'int4', PG::BinaryEncoder::Int4, PG::BinaryDecoder::Integer
243
- register_type 1, 'int8', PG::BinaryEncoder::Int8, PG::BinaryDecoder::Integer
244
- alias_type 1, 'oid', 'int2'
245
-
246
- register_type 1, 'text', PG::BinaryEncoder::String, PG::BinaryDecoder::String
247
- alias_type 1, 'varchar', 'text'
248
- alias_type 1, 'char', 'text'
249
- alias_type 1, 'bpchar', 'text'
250
- alias_type 1, 'xml', 'text'
251
-
252
- register_type 1, 'bytea', PG::BinaryEncoder::Bytea, PG::BinaryDecoder::Bytea
253
- register_type 1, 'bool', PG::BinaryEncoder::Boolean, PG::BinaryDecoder::Boolean
254
- register_type 1, 'float4', nil, PG::BinaryDecoder::Float
255
- register_type 1, 'float8', nil, PG::BinaryDecoder::Float
256
- register_type 1, 'timestamp', nil, PG::BinaryDecoder::TimestampUtc
257
- register_type 1, 'timestamptz', nil, PG::BinaryDecoder::TimestampUtcToLocal
258
- end
259
-
260
- # Simple set of rules for type casting common PostgreSQL types to Ruby.
261
- #
262
- # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
263
- # PostgreSQL's +pg_type+ table in PG::BasicTypeMapForResults.new .
264
- #
265
- # Result values are type casted based on the type OID of the given result column.
266
- #
267
- # Higher level libraries will most likely not make use of this class, but use their
268
- # own set of rules to choose suitable encoders and decoders.
269
- #
270
- # Example:
271
- # conn = PG::Connection.new
272
- # # Assign a default ruleset for type casts of output values.
273
- # conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
274
- # # Execute a query.
275
- # res = conn.exec_params( "SELECT $1::INT", ['5'] )
276
- # # Retrieve and cast the result value. Value format is 0 (text) and OID is 20. Therefore typecasting
277
- # # is done by PG::TextDecoder::Integer internally for all value retrieval methods.
278
- # res.values # => [[5]]
279
- #
280
- # PG::TypeMapByOid#build_column_map(result) can be used to generate
281
- # a result independent PG::TypeMapByColumn type map, which can subsequently be used
282
- # to cast #get_copy_data fields:
283
- #
284
- # For the following table:
285
- # conn.exec( "CREATE TABLE copytable AS VALUES('a', 123, '{5,4,3}'::INT[])" )
286
- #
287
- # # Retrieve table OIDs per empty result set.
288
- # res = conn.exec( "SELECT * FROM copytable LIMIT 0" )
289
- # # Build a type map for common database to ruby type decoders.
290
- # btm = PG::BasicTypeMapForResults.new(conn)
291
- # # Build a PG::TypeMapByColumn with decoders suitable for copytable.
292
- # tm = btm.build_column_map( res )
293
- # row_decoder = PG::TextDecoder::CopyRow.new type_map: tm
294
- #
295
- # conn.copy_data( "COPY copytable TO STDOUT", row_decoder ) do |res|
296
- # while row=conn.get_copy_data
297
- # p row
298
- # end
299
- # end
300
- # This prints the rows with type casted columns:
301
- # ["a", 123, [5, 4, 3]]
302
- #
303
- # See also PG::BasicTypeMapBasedOnResult for the encoder direction and PG::BasicTypeRegistry for the definition of additional types.
304
- class PG::BasicTypeMapForResults < PG::TypeMapByOid
305
- include PG::BasicTypeRegistry
306
-
307
- class WarningTypeMap < PG::TypeMapInRuby
308
- def initialize(typenames)
309
- @already_warned = Hash.new{|h, k| h[k] = {} }
310
- @typenames_by_oid = typenames
311
- end
312
-
313
- def typecast_result_value(result, _tuple, field)
314
- format = result.fformat(field)
315
- oid = result.ftype(field)
316
- unless @already_warned[format][oid]
317
- $stderr.puts "Warning: no type cast defined for type #{@typenames_by_oid[format][oid].inspect} with oid #{oid}. Please cast this type explicitly to TEXT to be safe for future changes."
318
- @already_warned[format][oid] = true
319
- end
320
- super
321
- end
322
- end
323
-
324
- def initialize(connection)
325
- @coder_maps = build_coder_maps(connection)
326
-
327
- # Populate TypeMapByOid hash with decoders
328
- @coder_maps.map{|f| f[:decoder].coders }.flatten.each do |coder|
329
- add_coder(coder)
330
- end
331
-
332
- typenames = @coder_maps.map{|f| f[:decoder].typenames_by_oid }
333
- self.default_type_map = WarningTypeMap.new(typenames)
334
- end
335
- end
336
-
337
- # Simple set of rules for type casting common PostgreSQL types from Ruby
338
- # to PostgreSQL.
339
- #
340
- # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
341
- # PostgreSQL's +pg_type+ table in PG::BasicTypeMapBasedOnResult.new .
342
- #
343
- # This class works equal to PG::BasicTypeMapForResults, but does not define decoders for
344
- # the given result OIDs, but encoders. So it can be used to type cast field values based on
345
- # the type OID retrieved by a separate SQL query.
346
- #
347
- # PG::TypeMapByOid#build_column_map(result) can be used to generate a result independent
348
- # PG::TypeMapByColumn type map, which can subsequently be used to cast query bind parameters
349
- # or #put_copy_data fields.
350
- #
351
- # Example:
352
- # conn.exec( "CREATE TEMP TABLE copytable (t TEXT, i INT, ai INT[])" )
353
- #
354
- # # Retrieve table OIDs per empty result set.
355
- # res = conn.exec( "SELECT * FROM copytable LIMIT 0" )
356
- # # Build a type map for common ruby to database type encoders.
357
- # btm = PG::BasicTypeMapBasedOnResult.new(conn)
358
- # # Build a PG::TypeMapByColumn with encoders suitable for copytable.
359
- # tm = btm.build_column_map( res )
360
- # row_encoder = PG::TextEncoder::CopyRow.new type_map: tm
361
- #
362
- # conn.copy_data( "COPY copytable FROM STDIN", row_encoder ) do |res|
363
- # conn.put_copy_data ['a', 123, [5,4,3]]
364
- # end
365
- # This inserts a single row into copytable with type casts from ruby to
366
- # database types.
367
- class PG::BasicTypeMapBasedOnResult < PG::TypeMapByOid
368
- include PG::BasicTypeRegistry
369
-
370
- def initialize(connection)
371
- @coder_maps = build_coder_maps(connection)
372
-
373
- # Populate TypeMapByOid hash with encoders
374
- @coder_maps.map{|f| f[:encoder].coders }.flatten.each do |coder|
375
- add_coder(coder)
376
- end
377
- end
378
- end
379
-
380
- # Simple set of rules for type casting common Ruby types to PostgreSQL.
381
- #
382
- # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
383
- # PostgreSQL's pg_type table in PG::BasicTypeMapForQueries.new .
384
- #
385
- # Query params are type casted based on the class of the given value.
386
- #
387
- # Higher level libraries will most likely not make use of this class, but use their
388
- # own derivation of PG::TypeMapByClass or another set of rules to choose suitable
389
- # encoders and decoders for the values to be sent.
390
- #
391
- # Example:
392
- # conn = PG::Connection.new
393
- # # Assign a default ruleset for type casts of input and output values.
394
- # conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn)
395
- # # Execute a query. The Integer param value is typecasted internally by PG::BinaryEncoder::Int8.
396
- # # The format of the parameter is set to 0 (text) and the OID of this parameter is set to 20 (int8).
397
- # res = conn.exec_params( "SELECT $1", [5] )
398
- class PG::BasicTypeMapForQueries < PG::TypeMapByClass
399
- include PG::BasicTypeRegistry
400
-
401
- def initialize(connection)
402
- @coder_maps = build_coder_maps(connection)
403
- @array_encoders_by_klass = array_encoders_by_klass
404
- @encode_array_as = :array
405
- init_encoders
406
- end
407
-
408
- # Change the mechanism that is used to encode ruby array values
409
- #
410
- # Possible values:
411
- # * +:array+ : Encode the ruby array as a PostgreSQL array.
412
- # The array element type is inferred from the class of the first array element. This is the default.
413
- # * +:json+ : Encode the ruby array as a JSON document.
414
- # * +:record+ : Encode the ruby array as a composite type row.
415
- # * <code>"_type"</code> : Encode the ruby array as a particular PostgreSQL type.
416
- # All PostgreSQL array types are supported.
417
- # If there's an encoder registered for the elements +type+, it will be used.
418
- # Otherwise a string conversion (by +value.to_s+) is done.
419
- def encode_array_as=(pg_type)
420
- case pg_type
421
- when :array
422
- when :json
423
- when :record
424
- when /\A_/
425
- else
426
- raise ArgumentError, "invalid pg_type #{pg_type.inspect}"
427
- end
428
-
429
- @encode_array_as = pg_type
430
-
431
- init_encoders
432
- end
433
-
434
- attr_reader :encode_array_as
435
-
436
- private
437
-
438
- def init_encoders
439
- coders.each { |kl, c| self[kl] = nil } # Clear type map
440
- populate_encoder_list
441
- @textarray_encoder = coder_by_name(0, :encoder, '_text')
442
- end
443
-
444
- def coder_by_name(format, direction, name)
445
- check_format_and_direction(format, direction)
446
- @coder_maps[format][direction].coder_by_name(name)
447
- end
448
-
449
- def populate_encoder_list
450
- DEFAULT_TYPE_MAP.each do |klass, selector|
451
- if Array === selector
452
- format, name, oid_name = selector
453
- coder = coder_by_name(format, :encoder, name).dup
454
- if oid_name
455
- coder.oid = coder_by_name(format, :encoder, oid_name).oid
456
- else
457
- coder.oid = 0
458
- end
459
- self[klass] = coder
460
- else
461
-
462
- case @encode_array_as
463
- when :array
464
- self[klass] = selector
465
- when :json
466
- self[klass] = PG::TextEncoder::JSON.new
467
- when :record
468
- self[klass] = PG::TextEncoder::Record.new type_map: self
469
- when /\A_/
470
- self[klass] = coder_by_name(0, :encoder, @encode_array_as) || raise(ArgumentError, "unknown array type #{@encode_array_as.inspect}")
471
- else
472
- raise ArgumentError, "invalid pg_type #{@encode_array_as.inspect}"
473
- end
474
- end
475
- end
476
- end
477
-
478
- def array_encoders_by_klass
479
- DEFAULT_ARRAY_TYPE_MAP.inject({}) do |h, (klass, (format, name))|
480
- h[klass] = coder_by_name(format, :encoder, name)
481
- h
482
- end
483
- end
484
-
485
- def get_array_type(value)
486
- elem = value
487
- while elem.kind_of?(Array)
488
- elem = elem.first
489
- end
490
- @array_encoders_by_klass[elem.class] ||
491
- elem.class.ancestors.lazy.map{|ancestor| @array_encoders_by_klass[ancestor] }.find{|a| a } ||
492
- @textarray_encoder
493
- end
494
-
495
- DEFAULT_TYPE_MAP = {
496
- TrueClass => [1, 'bool', 'bool'],
497
- FalseClass => [1, 'bool', 'bool'],
498
- # We use text format and no type OID for numbers, because setting the OID can lead
499
- # to unnecessary type conversions on server side.
500
- Integer => [0, 'int8'],
501
- Float => [0, 'float8'],
502
- BigDecimal => [0, 'numeric'],
503
- Time => [0, 'timestamptz'],
504
- # We use text format and no type OID for IPAddr, because setting the OID can lead
505
- # to unnecessary inet/cidr conversions on the server side.
506
- IPAddr => [0, 'inet'],
507
- Hash => [0, 'json'],
508
- Array => :get_array_type,
509
- }
510
-
511
- DEFAULT_ARRAY_TYPE_MAP = {
512
- TrueClass => [0, '_bool'],
513
- FalseClass => [0, '_bool'],
514
- Integer => [0, '_int8'],
515
- String => [0, '_text'],
516
- Float => [0, '_float8'],
517
- BigDecimal => [0, '_numeric'],
518
- Time => [0, '_timestamptz'],
519
- IPAddr => [0, '_inet'],
520
- }
521
-
522
- end
@@ -1,26 +0,0 @@
1
- To backend> Msg Q
2
- To backend> "SELECT 1 AS one"
3
- To backend> Msg complete, length 21
4
- From backend> T
5
- From backend (#4)> 28
6
- From backend (#2)> 1
7
- From backend> "one"
8
- From backend (#4)> 0
9
- From backend (#2)> 0
10
- From backend (#4)> 23
11
- From backend (#2)> 4
12
- From backend (#4)> -1
13
- From backend (#2)> 0
14
- From backend> D
15
- From backend (#4)> 11
16
- From backend (#2)> 1
17
- From backend (#4)> 1
18
- From backend (1)> 1
19
- From backend> C
20
- From backend (#4)> 11
21
- From backend> "SELECT"
22
- From backend> Z
23
- From backend (#4)> 5
24
- From backend> Z
25
- From backend (#4)> 5
26
- From backend> T
Binary file