pg 1.0.0 → 1.5.9

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 (126) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/Gemfile +20 -0
  4. data/History.md +932 -0
  5. data/Manifest.txt +8 -3
  6. data/README-Windows.rdoc +4 -4
  7. data/README.ja.md +300 -0
  8. data/README.md +286 -0
  9. data/Rakefile +41 -138
  10. data/Rakefile.cross +71 -66
  11. data/certs/ged.pem +24 -0
  12. data/certs/kanis@comcard.de.pem +20 -0
  13. data/certs/larskanis-2022.pem +26 -0
  14. data/certs/larskanis-2023.pem +24 -0
  15. data/certs/larskanis-2024.pem +24 -0
  16. data/ext/errorcodes.def +84 -5
  17. data/ext/errorcodes.rb +1 -1
  18. data/ext/errorcodes.txt +23 -6
  19. data/ext/extconf.rb +109 -25
  20. data/ext/gvl_wrappers.c +4 -0
  21. data/ext/gvl_wrappers.h +23 -0
  22. data/ext/pg.c +213 -155
  23. data/ext/pg.h +89 -23
  24. data/ext/pg_binary_decoder.c +164 -16
  25. data/ext/pg_binary_encoder.c +238 -13
  26. data/ext/pg_coder.c +159 -35
  27. data/ext/pg_connection.c +1584 -967
  28. data/ext/pg_copy_coder.c +373 -43
  29. data/ext/pg_errors.c +1 -1
  30. data/ext/pg_record_coder.c +522 -0
  31. data/ext/pg_result.c +710 -217
  32. data/ext/pg_text_decoder.c +630 -43
  33. data/ext/pg_text_encoder.c +222 -72
  34. data/ext/pg_tuple.c +572 -0
  35. data/ext/pg_type_map.c +45 -11
  36. data/ext/pg_type_map_all_strings.c +21 -7
  37. data/ext/pg_type_map_by_class.c +59 -27
  38. data/ext/pg_type_map_by_column.c +80 -37
  39. data/ext/pg_type_map_by_mri_type.c +49 -20
  40. data/ext/pg_type_map_by_oid.c +62 -29
  41. data/ext/pg_type_map_in_ruby.c +56 -22
  42. data/ext/{util.c → pg_util.c} +12 -12
  43. data/ext/{util.h → pg_util.h} +2 -2
  44. data/lib/pg/basic_type_map_based_on_result.rb +67 -0
  45. data/lib/pg/basic_type_map_for_queries.rb +202 -0
  46. data/lib/pg/basic_type_map_for_results.rb +104 -0
  47. data/lib/pg/basic_type_registry.rb +311 -0
  48. data/lib/pg/binary_decoder/date.rb +9 -0
  49. data/lib/pg/binary_decoder/timestamp.rb +26 -0
  50. data/lib/pg/binary_encoder/timestamp.rb +20 -0
  51. data/lib/pg/coder.rb +36 -13
  52. data/lib/pg/connection.rb +769 -70
  53. data/lib/pg/exceptions.rb +22 -2
  54. data/lib/pg/result.rb +14 -2
  55. data/lib/pg/text_decoder/date.rb +21 -0
  56. data/lib/pg/text_decoder/inet.rb +9 -0
  57. data/lib/pg/text_decoder/json.rb +17 -0
  58. data/lib/pg/text_decoder/numeric.rb +9 -0
  59. data/lib/pg/text_decoder/timestamp.rb +30 -0
  60. data/lib/pg/text_encoder/date.rb +13 -0
  61. data/lib/pg/text_encoder/inet.rb +31 -0
  62. data/lib/pg/text_encoder/json.rb +17 -0
  63. data/lib/pg/text_encoder/numeric.rb +9 -0
  64. data/lib/pg/text_encoder/timestamp.rb +24 -0
  65. data/lib/pg/tuple.rb +30 -0
  66. data/lib/pg/type_map_by_column.rb +3 -2
  67. data/lib/pg/version.rb +4 -0
  68. data/lib/pg.rb +106 -39
  69. data/misc/openssl-pg-segfault.rb +31 -0
  70. data/misc/postgres/History.txt +9 -0
  71. data/misc/postgres/Manifest.txt +5 -0
  72. data/misc/postgres/README.txt +21 -0
  73. data/misc/postgres/Rakefile +21 -0
  74. data/misc/postgres/lib/postgres.rb +16 -0
  75. data/misc/ruby-pg/History.txt +9 -0
  76. data/misc/ruby-pg/Manifest.txt +5 -0
  77. data/misc/ruby-pg/README.txt +21 -0
  78. data/misc/ruby-pg/Rakefile +21 -0
  79. data/misc/ruby-pg/lib/ruby/pg.rb +16 -0
  80. data/pg.gemspec +36 -0
  81. data/rakelib/task_extension.rb +46 -0
  82. data/sample/array_insert.rb +20 -0
  83. data/sample/async_api.rb +102 -0
  84. data/sample/async_copyto.rb +39 -0
  85. data/sample/async_mixed.rb +56 -0
  86. data/sample/check_conn.rb +21 -0
  87. data/sample/copydata.rb +71 -0
  88. data/sample/copyfrom.rb +81 -0
  89. data/sample/copyto.rb +19 -0
  90. data/sample/cursor.rb +21 -0
  91. data/sample/disk_usage_report.rb +177 -0
  92. data/sample/issue-119.rb +94 -0
  93. data/sample/losample.rb +69 -0
  94. data/sample/minimal-testcase.rb +17 -0
  95. data/sample/notify_wait.rb +72 -0
  96. data/sample/pg_statistics.rb +285 -0
  97. data/sample/replication_monitor.rb +222 -0
  98. data/sample/test_binary_values.rb +33 -0
  99. data/sample/wal_shipper.rb +434 -0
  100. data/sample/warehouse_partitions.rb +311 -0
  101. data.tar.gz.sig +0 -0
  102. metadata +138 -223
  103. metadata.gz.sig +0 -0
  104. data/.gemtest +0 -0
  105. data/ChangeLog +0 -6595
  106. data/History.rdoc +0 -422
  107. data/README.ja.rdoc +0 -14
  108. data/README.rdoc +0 -167
  109. data/lib/pg/basic_type_mapping.rb +0 -426
  110. data/lib/pg/constants.rb +0 -11
  111. data/lib/pg/text_decoder.rb +0 -51
  112. data/lib/pg/text_encoder.rb +0 -35
  113. data/spec/data/expected_trace.out +0 -26
  114. data/spec/data/random_binary_data +0 -0
  115. data/spec/helpers.rb +0 -348
  116. data/spec/pg/basic_type_mapping_spec.rb +0 -305
  117. data/spec/pg/connection_spec.rb +0 -1719
  118. data/spec/pg/result_spec.rb +0 -456
  119. data/spec/pg/type_map_by_class_spec.rb +0 -138
  120. data/spec/pg/type_map_by_column_spec.rb +0 -222
  121. data/spec/pg/type_map_by_mri_type_spec.rb +0 -136
  122. data/spec/pg/type_map_by_oid_spec.rb +0 -149
  123. data/spec/pg/type_map_in_ruby_spec.rb +0 -164
  124. data/spec/pg/type_map_spec.rb +0 -22
  125. data/spec/pg/type_spec.rb +0 -777
  126. data/spec/pg_spec.rb +0 -50
@@ -1,426 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'pg' unless defined?( PG )
4
-
5
- module PG::BasicTypeRegistry
6
- # An instance of this class stores the coders that should be used for a given wire format (text or binary)
7
- # and type cast direction (encoder or decoder).
8
- class CoderMap
9
- # Hash of text types that don't require quotation, when used within composite types.
10
- # type.name => true
11
- DONT_QUOTE_TYPES = %w[
12
- int2 int4 int8
13
- float4 float8
14
- oid
15
- bool
16
- date timestamp timestamptz
17
- ].inject({}){|h,e| h[e] = true; h }
18
-
19
- def initialize(result, coders_by_name, format, arraycoder)
20
- coder_map = {}
21
-
22
- _ranges, nodes = result.partition { |row| row['typinput'] == 'range_in' }
23
- leaves, nodes = nodes.partition { |row| row['typelem'].to_i == 0 }
24
- arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' }
25
-
26
- # populate the enum types
27
- _enums, leaves = leaves.partition { |row| row['typinput'] == 'enum_in' }
28
- # enums.each do |row|
29
- # coder_map[row['oid'].to_i] = OID::Enum.new
30
- # end
31
-
32
- # populate the base types
33
- leaves.find_all { |row| coders_by_name.key?(row['typname']) }.each do |row|
34
- coder = coders_by_name[row['typname']].dup
35
- coder.oid = row['oid'].to_i
36
- coder.name = row['typname']
37
- coder.format = format
38
- coder_map[coder.oid] = coder
39
- end
40
-
41
- _records_by_oid = result.group_by { |row| row['oid'] }
42
-
43
- # populate composite types
44
- # nodes.each do |row|
45
- # add_oid row, records_by_oid, coder_map
46
- # end
47
-
48
- if arraycoder
49
- # populate array types
50
- arrays.each do |row|
51
- elements_coder = coder_map[row['typelem'].to_i]
52
- next unless elements_coder
53
-
54
- coder = arraycoder.new
55
- coder.oid = row['oid'].to_i
56
- coder.name = row['typname']
57
- coder.format = format
58
- coder.elements_type = elements_coder
59
- coder.needs_quotation = !DONT_QUOTE_TYPES[elements_coder.name]
60
- coder_map[coder.oid] = coder
61
- end
62
- end
63
-
64
- # populate range types
65
- # ranges.find_all { |row| coder_map.key? row['rngsubtype'].to_i }.each do |row|
66
- # subcoder = coder_map[row['rngsubtype'].to_i]
67
- # range = OID::Range.new subcoder
68
- # coder_map[row['oid'].to_i] = range
69
- # end
70
-
71
- @coders = coder_map.values
72
- @coders_by_name = @coders.inject({}){|h, t| h[t.name] = t; h }
73
- @coders_by_oid = @coders.inject({}){|h, t| h[t.oid] = t; h }
74
- @typenames_by_oid = result.inject({}){|h, t| h[t['oid'].to_i] = t['typname']; h }
75
- end
76
-
77
- attr_reader :coders
78
- attr_reader :coders_by_oid
79
- attr_reader :coders_by_name
80
- attr_reader :typenames_by_oid
81
-
82
- def coder_by_name(name)
83
- @coders_by_name[name]
84
- end
85
-
86
- def coder_by_oid(oid)
87
- @coders_by_oid[oid]
88
- end
89
- end
90
-
91
- private
92
-
93
- def supports_ranges?(connection)
94
- connection.server_version >= 90200
95
- end
96
-
97
- def build_coder_maps(connection)
98
- if supports_ranges?(connection)
99
- result = connection.exec <<-SQL
100
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype
101
- FROM pg_type as t
102
- LEFT JOIN pg_range as r ON oid = rngtypid
103
- SQL
104
- else
105
- result = connection.exec <<-SQL
106
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput
107
- FROM pg_type as t
108
- SQL
109
- end
110
-
111
- [
112
- [0, :encoder, PG::TextEncoder::Array],
113
- [0, :decoder, PG::TextDecoder::Array],
114
- [1, :encoder, nil],
115
- [1, :decoder, nil],
116
- ].inject([]) do |h, (format, direction, arraycoder)|
117
- h[format] ||= {}
118
- h[format][direction] = CoderMap.new result, CODERS_BY_NAME[format][direction], format, arraycoder
119
- h
120
- end
121
- end
122
-
123
- ValidFormats = { 0 => true, 1 => true }
124
- ValidDirections = { :encoder => true, :decoder => true }
125
-
126
- def check_format_and_direction(format, direction)
127
- raise(ArgumentError, "Invalid format value %p" % format) unless ValidFormats[format]
128
- raise(ArgumentError, "Invalid direction %p" % direction) unless ValidDirections[direction]
129
- end
130
- protected :check_format_and_direction
131
-
132
- # The key of this hash maps to the `typname` column from the table.
133
- # encoder_map is then dynamically built with oids as the key and Type
134
- # objects as values.
135
- CODERS_BY_NAME = []
136
-
137
- # Register an OID type named +name+ with a typecasting encoder and decoder object in
138
- # +type+. +name+ should correspond to the `typname` column in
139
- # the `pg_type` table.
140
- def self.register_type(format, name, encoder_class, decoder_class)
141
- CODERS_BY_NAME[format] ||= { encoder: {}, decoder: {} }
142
- CODERS_BY_NAME[format][:encoder][name] = encoder_class.new(name: name, format: format) if encoder_class
143
- CODERS_BY_NAME[format][:decoder][name] = decoder_class.new(name: name, format: format) if decoder_class
144
- end
145
-
146
- # Alias the +old+ type to the +new+ type.
147
- def self.alias_type(format, new, old)
148
- CODERS_BY_NAME[format][:encoder][new] = CODERS_BY_NAME[format][:encoder][old]
149
- CODERS_BY_NAME[format][:decoder][new] = CODERS_BY_NAME[format][:decoder][old]
150
- end
151
-
152
- register_type 0, 'int2', PG::TextEncoder::Integer, PG::TextDecoder::Integer
153
- alias_type 0, 'int4', 'int2'
154
- alias_type 0, 'int8', 'int2'
155
- alias_type 0, 'oid', 'int2'
156
-
157
- # register_type 0, 'numeric', OID::Decimal.new
158
- register_type 0, 'text', PG::TextEncoder::String, PG::TextDecoder::String
159
- alias_type 0, 'varchar', 'text'
160
- alias_type 0, 'char', 'text'
161
- alias_type 0, 'bpchar', 'text'
162
- alias_type 0, 'xml', 'text'
163
-
164
- # FIXME: why are we keeping these types as strings?
165
- # alias_type 'tsvector', 'text'
166
- # alias_type 'interval', 'text'
167
- # alias_type 'macaddr', 'text'
168
- # alias_type 'uuid', 'text'
169
- #
170
- # register_type 'money', OID::Money.new
171
- # There is no PG::TextEncoder::Bytea, because it's simple and more efficient to send bytea-data
172
- # in binary format, either with PG::BinaryEncoder::Bytea or in Hash param format.
173
- register_type 0, 'bytea', nil, PG::TextDecoder::Bytea
174
- register_type 0, 'bool', PG::TextEncoder::Boolean, PG::TextDecoder::Boolean
175
- # register_type 'bit', OID::Bit.new
176
- # register_type 'varbit', OID::Bit.new
177
-
178
- register_type 0, 'float4', PG::TextEncoder::Float, PG::TextDecoder::Float
179
- alias_type 0, 'float8', 'float4'
180
-
181
- register_type 0, 'timestamp', PG::TextEncoder::TimestampWithoutTimeZone, PG::TextDecoder::TimestampWithoutTimeZone
182
- register_type 0, 'timestamptz', PG::TextEncoder::TimestampWithTimeZone, PG::TextDecoder::TimestampWithTimeZone
183
- register_type 0, 'date', PG::TextEncoder::Date, PG::TextDecoder::Date
184
- # register_type 'time', OID::Time.new
185
- #
186
- # register_type 'path', OID::Text.new
187
- # register_type 'point', OID::Point.new
188
- # register_type 'polygon', OID::Text.new
189
- # register_type 'circle', OID::Text.new
190
- # register_type 'hstore', OID::Hstore.new
191
- register_type 0, 'json', PG::TextEncoder::JSON, PG::TextDecoder::JSON
192
- alias_type 0, 'jsonb', 'json'
193
- # register_type 'citext', OID::Text.new
194
- # register_type 'ltree', OID::Text.new
195
- #
196
- # register_type 'cidr', OID::Cidr.new
197
- # alias_type 'inet', 'cidr'
198
-
199
-
200
-
201
- register_type 1, 'int2', PG::BinaryEncoder::Int2, PG::BinaryDecoder::Integer
202
- register_type 1, 'int4', PG::BinaryEncoder::Int4, PG::BinaryDecoder::Integer
203
- register_type 1, 'int8', PG::BinaryEncoder::Int8, PG::BinaryDecoder::Integer
204
- alias_type 1, 'oid', 'int2'
205
-
206
- register_type 1, 'text', PG::BinaryEncoder::String, PG::BinaryDecoder::String
207
- alias_type 1, 'varchar', 'text'
208
- alias_type 1, 'char', 'text'
209
- alias_type 1, 'bpchar', 'text'
210
- alias_type 1, 'xml', 'text'
211
-
212
- register_type 1, 'bytea', PG::BinaryEncoder::Bytea, PG::BinaryDecoder::Bytea
213
- register_type 1, 'bool', PG::BinaryEncoder::Boolean, PG::BinaryDecoder::Boolean
214
- register_type 1, 'float4', nil, PG::BinaryDecoder::Float
215
- register_type 1, 'float8', nil, PG::BinaryDecoder::Float
216
- end
217
-
218
- # Simple set of rules for type casting common PostgreSQL types to Ruby.
219
- #
220
- # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
221
- # PostgreSQL's pg_type table in PG::BasicTypeMapForResults.new .
222
- #
223
- # Result values are type casted based on the type OID of the given result column.
224
- #
225
- # Higher level libraries will most likely not make use of this class, but use their
226
- # own set of rules to choose suitable encoders and decoders.
227
- #
228
- # Example:
229
- # conn = PG::Connection.new
230
- # # Assign a default ruleset for type casts of output values.
231
- # conn.type_map_for_results = PG::BasicTypeMapForResults.new(conn)
232
- # # Execute a query.
233
- # res = conn.exec_params( "SELECT $1::INT", ['5'] )
234
- # # Retrieve and cast the result value. Value format is 0 (text) and OID is 20. Therefore typecasting
235
- # # is done by PG::TextDecoder::Integer internally for all value retrieval methods.
236
- # res.values # => [[5]]
237
- #
238
- # PG::TypeMapByOid#fit_to_result(result, false) can be used to generate
239
- # a result independent PG::TypeMapByColumn type map, which can subsequently be used
240
- # to cast #get_copy_data fields:
241
- #
242
- # For the following table:
243
- # conn.exec( "CREATE TABLE copytable AS VALUES('a', 123, '{5,4,3}'::INT[])" )
244
- #
245
- # # Retrieve table OIDs per empty result set.
246
- # res = conn.exec( "SELECT * FROM copytable LIMIT 0" )
247
- # # Build a type map for common database to ruby type decoders.
248
- # btm = PG::BasicTypeMapForResults.new(conn)
249
- # # Build a PG::TypeMapByColumn with decoders suitable for copytable.
250
- # tm = btm.build_column_map( res )
251
- # row_decoder = PG::TextDecoder::CopyRow.new type_map: tm
252
- #
253
- # conn.copy_data( "COPY copytable TO STDOUT", row_decoder ) do |res|
254
- # while row=conn.get_copy_data
255
- # p row
256
- # end
257
- # end
258
- # This prints the rows with type casted columns:
259
- # ["a", 123, [5, 4, 3]]
260
- #
261
- # See also PG::BasicTypeMapBasedOnResult for the encoder direction.
262
- class PG::BasicTypeMapForResults < PG::TypeMapByOid
263
- include PG::BasicTypeRegistry
264
-
265
- class WarningTypeMap < PG::TypeMapInRuby
266
- def initialize(typenames)
267
- @already_warned = Hash.new{|h, k| h[k] = {} }
268
- @typenames_by_oid = typenames
269
- end
270
-
271
- def typecast_result_value(result, _tuple, field)
272
- format = result.fformat(field)
273
- oid = result.ftype(field)
274
- unless @already_warned[format][oid]
275
- 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."
276
- @already_warned[format][oid] = true
277
- end
278
- super
279
- end
280
- end
281
-
282
- def initialize(connection)
283
- @coder_maps = build_coder_maps(connection)
284
-
285
- # Populate TypeMapByOid hash with decoders
286
- @coder_maps.map{|f| f[:decoder].coders }.flatten.each do |coder|
287
- add_coder(coder)
288
- end
289
-
290
- typenames = @coder_maps.map{|f| f[:decoder].typenames_by_oid }
291
- self.default_type_map = WarningTypeMap.new(typenames)
292
- end
293
- end
294
-
295
- # Simple set of rules for type casting common PostgreSQL types from Ruby
296
- # to PostgreSQL.
297
- #
298
- # OIDs of supported type casts are not hard-coded in the sources, but are retrieved from the
299
- # PostgreSQL's pg_type table in PG::BasicTypeMapBasedOnResult.new .
300
- #
301
- # This class works equal to PG::BasicTypeMapForResults, but does not define decoders for
302
- # the given result OIDs, but encoders. So it can be used to type cast field values based on
303
- # the type OID retrieved by a separate SQL query.
304
- #
305
- # PG::TypeMapByOid#build_column_map(result) can be used to generate a result independent
306
- # PG::TypeMapByColumn type map, which can subsequently be used to cast query bind parameters
307
- # or #put_copy_data fields.
308
- #
309
- # Example:
310
- # conn.exec( "CREATE TEMP TABLE copytable (t TEXT, i INT, ai INT[])" )
311
- #
312
- # # Retrieve table OIDs per empty result set.
313
- # res = conn.exec( "SELECT * FROM copytable LIMIT 0" )
314
- # # Build a type map for common ruby to database type encoders.
315
- # btm = PG::BasicTypeMapBasedOnResult.new(conn)
316
- # # Build a PG::TypeMapByColumn with encoders suitable for copytable.
317
- # tm = btm.build_column_map( res )
318
- # row_encoder = PG::TextEncoder::CopyRow.new type_map: tm
319
- #
320
- # conn.copy_data( "COPY copytable FROM STDIN", row_encoder ) do |res|
321
- # conn.put_copy_data ['a', 123, [5,4,3]]
322
- # end
323
- # This inserts a single row into copytable with type casts from ruby to
324
- # database types.
325
- class PG::BasicTypeMapBasedOnResult < PG::TypeMapByOid
326
- include PG::BasicTypeRegistry
327
-
328
- def initialize(connection)
329
- @coder_maps = build_coder_maps(connection)
330
-
331
- # Populate TypeMapByOid hash with encoders
332
- @coder_maps.map{|f| f[:encoder].coders }.flatten.each do |coder|
333
- add_coder(coder)
334
- end
335
- end
336
- end
337
-
338
- # Simple set of rules for type casting common Ruby types 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::BasicTypeMapForQueries.new .
342
- #
343
- # Query params are type casted based on the class of the given value.
344
- #
345
- # Higher level libraries will most likely not make use of this class, but use their
346
- # own derivation of PG::TypeMapByClass or another set of rules to choose suitable
347
- # encoders and decoders for the values to be sent.
348
- #
349
- # Example:
350
- # conn = PG::Connection.new
351
- # # Assign a default ruleset for type casts of input and output values.
352
- # conn.type_map_for_queries = PG::BasicTypeMapForQueries.new(conn)
353
- # # Execute a query. The Integer param value is typecasted internally by PG::BinaryEncoder::Int8.
354
- # # The format of the parameter is set to 1 (binary) and the OID of this parameter is set to 20 (int8).
355
- # res = conn.exec_params( "SELECT $1", [5] )
356
- class PG::BasicTypeMapForQueries < PG::TypeMapByClass
357
- include PG::BasicTypeRegistry
358
-
359
- def initialize(connection)
360
- @coder_maps = build_coder_maps(connection)
361
-
362
- populate_encoder_list
363
- @array_encoders_by_klass = array_encoders_by_klass
364
- @anyarray_encoder = coder_by_name(0, :encoder, '_any')
365
- end
366
-
367
- private
368
-
369
- def coder_by_name(format, direction, name)
370
- check_format_and_direction(format, direction)
371
- @coder_maps[format][direction].coder_by_name(name)
372
- end
373
-
374
- def populate_encoder_list
375
- DEFAULT_TYPE_MAP.each do |klass, selector|
376
- if Array === selector
377
- format, name, oid_name = selector
378
- coder = coder_by_name(format, :encoder, name).dup
379
- if oid_name
380
- coder.oid = coder_by_name(format, :encoder, oid_name).oid
381
- else
382
- coder.oid = 0
383
- end
384
- self[klass] = coder
385
- else
386
- self[klass] = selector
387
- end
388
- end
389
- end
390
-
391
- def array_encoders_by_klass
392
- DEFAULT_ARRAY_TYPE_MAP.inject({}) do |h, (klass, (format, name))|
393
- h[klass] = coder_by_name(format, :encoder, name)
394
- h
395
- end
396
- end
397
-
398
- def get_array_type(value)
399
- elem = value
400
- while elem.kind_of?(Array)
401
- elem = elem.first
402
- end
403
- @array_encoders_by_klass[elem.class] ||
404
- elem.class.ancestors.lazy.map{|ancestor| @array_encoders_by_klass[ancestor] }.find{|a| a } ||
405
- @anyarray_encoder
406
- end
407
-
408
- DEFAULT_TYPE_MAP = {
409
- TrueClass => [1, 'bool', 'bool'],
410
- FalseClass => [1, 'bool', 'bool'],
411
- # We use text format and no type OID for numbers, because setting the OID can lead
412
- # to unnecessary type conversions on server side.
413
- Integer => [0, 'int8'],
414
- Float => [0, 'float8'],
415
- Array => :get_array_type,
416
- }
417
-
418
- DEFAULT_ARRAY_TYPE_MAP = {
419
- TrueClass => [0, '_bool'],
420
- FalseClass => [0, '_bool'],
421
- Integer => [0, '_int8'],
422
- String => [0, '_text'],
423
- Float => [0, '_float8'],
424
- }
425
-
426
- end
data/lib/pg/constants.rb DELETED
@@ -1,11 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'pg' unless defined?( PG )
4
-
5
-
6
- module PG::Constants
7
-
8
- # Most of these are defined in the extension.
9
-
10
- end # module PG::Constants
11
-
@@ -1,51 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'date'
4
- require 'json'
5
-
6
- module PG
7
- module TextDecoder
8
- class Date < SimpleDecoder
9
- ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
10
-
11
- def decode(string, tuple=nil, field=nil)
12
- if string =~ ISO_DATE
13
- ::Date.new $1.to_i, $2.to_i, $3.to_i
14
- else
15
- string
16
- end
17
- end
18
- end
19
-
20
- class TimestampWithoutTimeZone < SimpleDecoder
21
- ISO_DATETIME_WITHOUT_TIMEZONE = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
22
-
23
- def decode(string, tuple=nil, field=nil)
24
- if string =~ ISO_DATETIME_WITHOUT_TIMEZONE
25
- Time.new $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, "#{$6}#{$7}".to_r
26
- else
27
- string
28
- end
29
- end
30
- end
31
-
32
- class TimestampWithTimeZone < SimpleDecoder
33
- ISO_DATETIME_WITH_TIMEZONE = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?([-\+]\d\d):?(\d\d)?:?(\d\d)?\z/
34
-
35
- def decode(string, tuple=nil, field=nil)
36
- if string =~ ISO_DATETIME_WITH_TIMEZONE
37
- Time.new $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, "#{$6}#{$7}".to_r, "#{$8}:#{$9 || '00'}:#{$10 || '00'}"
38
- else
39
- string
40
- end
41
- end
42
- end
43
-
44
- class JSON < SimpleDecoder
45
- def decode(string, tuple=nil, field=nil)
46
- ::JSON.parse(string, quirks_mode: true)
47
- end
48
- end
49
- end
50
- end # module PG
51
-
@@ -1,35 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require 'json'
4
-
5
- module PG
6
- module TextEncoder
7
- class Date < SimpleEncoder
8
- STRFTIME_ISO_DATE = "%Y-%m-%d".freeze
9
- def encode(value)
10
- value.respond_to?(:strftime) ? value.strftime(STRFTIME_ISO_DATE) : value
11
- end
12
- end
13
-
14
- class TimestampWithoutTimeZone < SimpleEncoder
15
- STRFTIME_ISO_DATETIME_WITHOUT_TIMEZONE = "%Y-%m-%d %H:%M:%S.%N".freeze
16
- def encode(value)
17
- value.respond_to?(:strftime) ? value.strftime(STRFTIME_ISO_DATETIME_WITHOUT_TIMEZONE) : value
18
- end
19
- end
20
-
21
- class TimestampWithTimeZone < SimpleEncoder
22
- STRFTIME_ISO_DATETIME_WITH_TIMEZONE = "%Y-%m-%d %H:%M:%S.%N %:z".freeze
23
- def encode(value)
24
- value.respond_to?(:strftime) ? value.strftime(STRFTIME_ISO_DATETIME_WITH_TIMEZONE) : value
25
- end
26
- end
27
-
28
- class JSON < SimpleEncoder
29
- def encode(value)
30
- ::JSON.generate(value, quirks_mode: true)
31
- end
32
- end
33
- end
34
- end # module PG
35
-
@@ -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