activerecord 4.1.15 → 4.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (167) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +634 -2176
  3. data/README.rdoc +15 -10
  4. data/lib/active_record/aggregations.rb +12 -8
  5. data/lib/active_record/associations/association.rb +1 -1
  6. data/lib/active_record/associations/association_scope.rb +53 -21
  7. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  8. data/lib/active_record/associations/builder/association.rb +16 -5
  9. data/lib/active_record/associations/builder/belongs_to.rb +7 -29
  10. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -11
  11. data/lib/active_record/associations/builder/has_one.rb +2 -2
  12. data/lib/active_record/associations/builder/singular_association.rb +8 -1
  13. data/lib/active_record/associations/collection_association.rb +32 -44
  14. data/lib/active_record/associations/collection_proxy.rb +1 -10
  15. data/lib/active_record/associations/has_many_association.rb +60 -14
  16. data/lib/active_record/associations/has_many_through_association.rb +34 -23
  17. data/lib/active_record/associations/has_one_association.rb +0 -1
  18. data/lib/active_record/associations/join_dependency/join_association.rb +18 -14
  19. data/lib/active_record/associations/join_dependency.rb +7 -9
  20. data/lib/active_record/associations/preloader/association.rb +9 -5
  21. data/lib/active_record/associations/preloader/through_association.rb +3 -3
  22. data/lib/active_record/associations/preloader.rb +2 -2
  23. data/lib/active_record/associations/singular_association.rb +16 -1
  24. data/lib/active_record/associations/through_association.rb +6 -22
  25. data/lib/active_record/associations.rb +58 -33
  26. data/lib/active_record/attribute.rb +131 -0
  27. data/lib/active_record/attribute_assignment.rb +19 -11
  28. data/lib/active_record/attribute_decorators.rb +66 -0
  29. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -2
  30. data/lib/active_record/attribute_methods/dirty.rb +85 -42
  31. data/lib/active_record/attribute_methods/primary_key.rb +6 -8
  32. data/lib/active_record/attribute_methods/read.rb +14 -57
  33. data/lib/active_record/attribute_methods/serialization.rb +12 -146
  34. data/lib/active_record/attribute_methods/time_zone_conversion.rb +32 -40
  35. data/lib/active_record/attribute_methods/write.rb +8 -23
  36. data/lib/active_record/attribute_methods.rb +53 -90
  37. data/lib/active_record/attribute_set/builder.rb +32 -0
  38. data/lib/active_record/attribute_set.rb +77 -0
  39. data/lib/active_record/attributes.rb +122 -0
  40. data/lib/active_record/autosave_association.rb +11 -21
  41. data/lib/active_record/base.rb +9 -19
  42. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +69 -45
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +22 -42
  44. data/lib/active_record/connection_adapters/abstract/quoting.rb +59 -60
  45. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +37 -2
  46. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +102 -21
  47. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +9 -33
  48. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +178 -55
  49. data/lib/active_record/connection_adapters/abstract/transaction.rb +120 -115
  50. data/lib/active_record/connection_adapters/abstract_adapter.rb +143 -57
  51. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +156 -107
  52. data/lib/active_record/connection_adapters/column.rb +13 -244
  53. data/lib/active_record/connection_adapters/connection_specification.rb +6 -20
  54. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -15
  55. data/lib/active_record/connection_adapters/mysql_adapter.rb +55 -143
  56. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +15 -27
  57. data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
  58. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +39 -20
  59. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +96 -0
  60. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
  61. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
  62. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +14 -0
  63. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
  64. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
  65. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +27 -0
  66. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
  67. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +17 -0
  68. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
  69. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
  70. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
  73. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
  74. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
  77. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +76 -0
  78. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +15 -0
  79. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
  80. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +85 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
  84. data/lib/active_record/connection_adapters/postgresql/oid.rb +29 -388
  85. data/lib/active_record/connection_adapters/postgresql/quoting.rb +42 -122
  86. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +4 -4
  87. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +154 -0
  88. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +86 -34
  89. data/lib/active_record/connection_adapters/postgresql/utils.rb +66 -0
  90. data/lib/active_record/connection_adapters/postgresql_adapter.rb +188 -452
  91. data/lib/active_record/connection_adapters/schema_cache.rb +14 -28
  92. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +54 -47
  93. data/lib/active_record/connection_handling.rb +1 -1
  94. data/lib/active_record/core.rb +119 -22
  95. data/lib/active_record/counter_cache.rb +60 -6
  96. data/lib/active_record/enum.rb +9 -10
  97. data/lib/active_record/errors.rb +27 -26
  98. data/lib/active_record/explain.rb +1 -1
  99. data/lib/active_record/fixtures.rb +52 -45
  100. data/lib/active_record/gem_version.rb +3 -3
  101. data/lib/active_record/inheritance.rb +33 -8
  102. data/lib/active_record/integration.rb +4 -4
  103. data/lib/active_record/locking/optimistic.rb +34 -16
  104. data/lib/active_record/migration/command_recorder.rb +19 -2
  105. data/lib/active_record/migration/join_table.rb +1 -1
  106. data/lib/active_record/migration.rb +22 -32
  107. data/lib/active_record/model_schema.rb +39 -48
  108. data/lib/active_record/nested_attributes.rb +8 -18
  109. data/lib/active_record/persistence.rb +39 -22
  110. data/lib/active_record/query_cache.rb +3 -3
  111. data/lib/active_record/querying.rb +1 -8
  112. data/lib/active_record/railtie.rb +17 -10
  113. data/lib/active_record/railties/databases.rake +47 -42
  114. data/lib/active_record/readonly_attributes.rb +0 -1
  115. data/lib/active_record/reflection.rb +225 -92
  116. data/lib/active_record/relation/batches.rb +0 -2
  117. data/lib/active_record/relation/calculations.rb +28 -32
  118. data/lib/active_record/relation/delegation.rb +1 -1
  119. data/lib/active_record/relation/finder_methods.rb +42 -20
  120. data/lib/active_record/relation/merger.rb +0 -1
  121. data/lib/active_record/relation/predicate_builder/array_handler.rb +16 -11
  122. data/lib/active_record/relation/predicate_builder/relation_handler.rb +0 -4
  123. data/lib/active_record/relation/predicate_builder.rb +1 -22
  124. data/lib/active_record/relation/query_methods.rb +98 -62
  125. data/lib/active_record/relation/spawn_methods.rb +6 -7
  126. data/lib/active_record/relation.rb +35 -11
  127. data/lib/active_record/result.rb +16 -9
  128. data/lib/active_record/sanitization.rb +8 -1
  129. data/lib/active_record/schema.rb +0 -1
  130. data/lib/active_record/schema_dumper.rb +51 -9
  131. data/lib/active_record/schema_migration.rb +4 -0
  132. data/lib/active_record/scoping/default.rb +5 -4
  133. data/lib/active_record/serializers/xml_serializer.rb +3 -7
  134. data/lib/active_record/statement_cache.rb +79 -5
  135. data/lib/active_record/store.rb +5 -5
  136. data/lib/active_record/tasks/database_tasks.rb +37 -5
  137. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  138. data/lib/active_record/tasks/postgresql_database_tasks.rb +2 -2
  139. data/lib/active_record/timestamp.rb +9 -7
  140. data/lib/active_record/transactions.rb +35 -21
  141. data/lib/active_record/type/binary.rb +40 -0
  142. data/lib/active_record/type/boolean.rb +19 -0
  143. data/lib/active_record/type/date.rb +46 -0
  144. data/lib/active_record/type/date_time.rb +43 -0
  145. data/lib/active_record/type/decimal.rb +40 -0
  146. data/lib/active_record/type/decimal_without_scale.rb +11 -0
  147. data/lib/active_record/type/float.rb +19 -0
  148. data/lib/active_record/type/hash_lookup_type_map.rb +19 -0
  149. data/lib/active_record/type/integer.rb +23 -0
  150. data/lib/active_record/type/mutable.rb +16 -0
  151. data/lib/active_record/type/numeric.rb +36 -0
  152. data/lib/active_record/type/serialized.rb +51 -0
  153. data/lib/active_record/type/string.rb +36 -0
  154. data/lib/active_record/type/text.rb +11 -0
  155. data/lib/active_record/type/time.rb +26 -0
  156. data/lib/active_record/type/time_value.rb +38 -0
  157. data/lib/active_record/type/type_map.rb +48 -0
  158. data/lib/active_record/type/value.rb +101 -0
  159. data/lib/active_record/type.rb +20 -0
  160. data/lib/active_record/validations/uniqueness.rb +9 -23
  161. data/lib/active_record/validations.rb +21 -16
  162. data/lib/active_record.rb +2 -1
  163. data/lib/rails/generators/active_record/migration/migration_generator.rb +8 -4
  164. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +1 -1
  165. data/lib/rails/generators/active_record/model/templates/model.rb +1 -1
  166. metadata +71 -14
  167. data/lib/active_record/connection_adapters/postgresql/cast.rb +0 -168
@@ -1,394 +1,35 @@
1
- require 'active_record/connection_adapters/abstract_adapter'
1
+ require 'active_record/connection_adapters/postgresql/oid/infinity'
2
+
3
+ require 'active_record/connection_adapters/postgresql/oid/array'
4
+ require 'active_record/connection_adapters/postgresql/oid/bit'
5
+ require 'active_record/connection_adapters/postgresql/oid/bit_varying'
6
+ require 'active_record/connection_adapters/postgresql/oid/bytea'
7
+ require 'active_record/connection_adapters/postgresql/oid/cidr'
8
+ require 'active_record/connection_adapters/postgresql/oid/date'
9
+ require 'active_record/connection_adapters/postgresql/oid/date_time'
10
+ require 'active_record/connection_adapters/postgresql/oid/decimal'
11
+ require 'active_record/connection_adapters/postgresql/oid/enum'
12
+ require 'active_record/connection_adapters/postgresql/oid/float'
13
+ require 'active_record/connection_adapters/postgresql/oid/hstore'
14
+ require 'active_record/connection_adapters/postgresql/oid/inet'
15
+ require 'active_record/connection_adapters/postgresql/oid/integer'
16
+ require 'active_record/connection_adapters/postgresql/oid/json'
17
+ require 'active_record/connection_adapters/postgresql/oid/jsonb'
18
+ require 'active_record/connection_adapters/postgresql/oid/money'
19
+ require 'active_record/connection_adapters/postgresql/oid/point'
20
+ require 'active_record/connection_adapters/postgresql/oid/range'
21
+ require 'active_record/connection_adapters/postgresql/oid/specialized_string'
22
+ require 'active_record/connection_adapters/postgresql/oid/time'
23
+ require 'active_record/connection_adapters/postgresql/oid/uuid'
24
+ require 'active_record/connection_adapters/postgresql/oid/vector'
25
+ require 'active_record/connection_adapters/postgresql/oid/xml'
26
+
27
+ require 'active_record/connection_adapters/postgresql/oid/type_map_initializer'
2
28
 
3
29
  module ActiveRecord
4
30
  module ConnectionAdapters
5
- class PostgreSQLAdapter < AbstractAdapter
6
- module OID
7
- class Type
8
- def type; end
9
- end
10
-
11
- class Identity < Type
12
- def type_cast(value)
13
- value
14
- end
15
- end
16
-
17
- class Bit < Type
18
- def type_cast(value)
19
- if String === value
20
- ConnectionAdapters::PostgreSQLColumn.string_to_bit value
21
- else
22
- value
23
- end
24
- end
25
- end
26
-
27
- class Bytea < Type
28
- def type_cast(value)
29
- return if value.nil?
30
- # This is a flawed heuristic, but it avoids truncation;
31
- # we really shouldn’t be calling this with already-unescaped values
32
- return value if value.dup.force_encoding("BINARY") =~ /\x00/
33
- PGconn.unescape_bytea value
34
- end
35
- end
36
-
37
- class Money < Type
38
- def type_cast(value)
39
- return if value.nil?
40
- return value unless String === value
41
-
42
- # Because money output is formatted according to the locale, there are two
43
- # cases to consider (note the decimal separators):
44
- # (1) $12,345,678.12
45
- # (2) $12.345.678,12
46
- # Negative values are represented as follows:
47
- # (3) -$2.55
48
- # (4) ($2.55)
49
-
50
- value.sub!(/^\((.+)\)$/, '-\1') # (4)
51
- case value
52
- when /^-?\D+[\d,]+\.\d{2}$/ # (1)
53
- value.gsub!(/[^-\d.]/, '')
54
- when /^-?\D+[\d.]+,\d{2}$/ # (2)
55
- value.gsub!(/[^-\d,]/, '').sub!(/,/, '.')
56
- end
57
-
58
- ConnectionAdapters::Column.value_to_decimal value
59
- end
60
- end
61
-
62
- class Vector < Type
63
- attr_reader :delim, :subtype
64
-
65
- # +delim+ corresponds to the `typdelim` column in the pg_types
66
- # table. +subtype+ is derived from the `typelem` column in the
67
- # pg_types table.
68
- def initialize(delim, subtype)
69
- @delim = delim
70
- @subtype = subtype
71
- end
72
-
73
- # FIXME: this should probably split on +delim+ and use +subtype+
74
- # to cast the values. Unfortunately, the current Rails behavior
75
- # is to just return the string.
76
- def type_cast(value)
77
- value
78
- end
79
- end
80
-
81
- class Point < Type
82
- def type_cast(value)
83
- if String === value
84
- ConnectionAdapters::PostgreSQLColumn.string_to_point value
85
- else
86
- value
87
- end
88
- end
89
- end
90
-
91
- class Array < Type
92
- attr_reader :subtype
93
- def initialize(subtype)
94
- @subtype = subtype
95
- end
96
-
97
- def type_cast(value)
98
- if String === value
99
- ConnectionAdapters::PostgreSQLColumn.string_to_array value, @subtype
100
- else
101
- value
102
- end
103
- end
104
- end
105
-
106
- class Range < Type
107
- attr_reader :subtype
108
- def initialize(subtype)
109
- @subtype = subtype
110
- end
111
-
112
- def extract_bounds(value)
113
- from, to = value[1..-2].split(',')
114
- {
115
- from: (value[1] == ',' || from == '-infinity') ? infinity(:negative => true) : from,
116
- to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
117
- exclude_start: (value[0] == '('),
118
- exclude_end: (value[-1] == ')')
119
- }
120
- end
121
-
122
- def infinity(options = {})
123
- ::Float::INFINITY * (options[:negative] ? -1 : 1)
124
- end
125
-
126
- def infinity?(value)
127
- value.respond_to?(:infinite?) && value.infinite?
128
- end
129
-
130
- def to_integer(value)
131
- infinity?(value) ? value : value.to_i
132
- end
133
-
134
- def type_cast(value)
135
- return if value.nil? || value == 'empty'
136
- return value if value.is_a?(::Range)
137
-
138
- extracted = extract_bounds(value)
139
-
140
- case @subtype
141
- when :date
142
- from = ConnectionAdapters::Column.value_to_date(extracted[:from])
143
- from += 1.day if extracted[:exclude_start]
144
- to = ConnectionAdapters::Column.value_to_date(extracted[:to])
145
- when :decimal
146
- from = BigDecimal.new(extracted[:from].to_s)
147
- # FIXME: add exclude start for ::Range, same for timestamp ranges
148
- to = BigDecimal.new(extracted[:to].to_s)
149
- when :time
150
- from = ConnectionAdapters::Column.string_to_time(extracted[:from])
151
- to = ConnectionAdapters::Column.string_to_time(extracted[:to])
152
- when :integer
153
- from = to_integer(extracted[:from]) rescue value ? 1 : 0
154
- from += 1 if extracted[:exclude_start]
155
- to = to_integer(extracted[:to]) rescue value ? 1 : 0
156
- else
157
- return value
158
- end
159
-
160
- ::Range.new(from, to, extracted[:exclude_end])
161
- end
162
- end
163
-
164
- class Integer < Type
165
- def type_cast(value)
166
- return if value.nil?
167
-
168
- ConnectionAdapters::Column.value_to_integer value
169
- end
170
- end
171
-
172
- class Boolean < Type
173
- def type_cast(value)
174
- return if value.nil?
175
-
176
- ConnectionAdapters::Column.value_to_boolean value
177
- end
178
- end
179
-
180
- class Timestamp < Type
181
- def type; :timestamp; end
182
-
183
- def type_cast(value)
184
- return if value.nil?
185
-
186
- # FIXME: probably we can improve this since we know it is PG
187
- # specific
188
- ConnectionAdapters::PostgreSQLColumn.string_to_time value
189
- end
190
- end
191
-
192
- class Date < Type
193
- def type; :datetime; end
194
-
195
- def type_cast(value)
196
- return if value.nil?
197
-
198
- # FIXME: probably we can improve this since we know it is PG
199
- # specific
200
- ConnectionAdapters::Column.value_to_date value
201
- end
202
- end
203
-
204
- class Time < Type
205
- def type_cast(value)
206
- return if value.nil?
207
-
208
- # FIXME: probably we can improve this since we know it is PG
209
- # specific
210
- ConnectionAdapters::Column.string_to_dummy_time value
211
- end
212
- end
213
-
214
- class Float < Type
215
- def type_cast(value)
216
- case value
217
- when nil; nil
218
- when 'Infinity'; ::Float::INFINITY
219
- when '-Infinity'; -::Float::INFINITY
220
- when 'NaN'; ::Float::NAN
221
- else
222
- value.to_f
223
- end
224
- end
225
- end
226
-
227
- class Decimal < Type
228
- def type_cast(value)
229
- return if value.nil?
230
-
231
- ConnectionAdapters::Column.value_to_decimal value
232
- end
233
- end
234
-
235
- class Hstore < Type
236
- def type_cast_for_write(value)
237
- # roundtrip to ensure uniform uniform types
238
- # TODO: This is not an efficient solution.
239
- stringified = ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value)
240
- type_cast(stringified)
241
- end
242
-
243
- def type_cast(value)
244
- return if value.nil?
245
-
246
- ConnectionAdapters::PostgreSQLColumn.string_to_hstore value
247
- end
248
-
249
- def accessor
250
- ActiveRecord::Store::StringKeyedHashAccessor
251
- end
252
- end
253
-
254
- class Cidr < Type
255
- def type_cast(value)
256
- return if value.nil?
257
-
258
- ConnectionAdapters::PostgreSQLColumn.string_to_cidr value
259
- end
260
- end
261
-
262
- class Json < Type
263
- def type_cast_for_write(value)
264
- # roundtrip to ensure uniform uniform types
265
- # TODO: This is not an efficient solution.
266
- stringified = ConnectionAdapters::PostgreSQLColumn.json_to_string(value)
267
- type_cast(stringified)
268
- end
269
-
270
- def type_cast(value)
271
- return if value.nil?
272
-
273
- ConnectionAdapters::PostgreSQLColumn.string_to_json value
274
- end
275
-
276
- def accessor
277
- ActiveRecord::Store::StringKeyedHashAccessor
278
- end
279
- end
280
-
281
- class TypeMap
282
- def initialize
283
- @mapping = {}
284
- end
285
-
286
- def []=(oid, type)
287
- @mapping[oid] = type
288
- end
289
-
290
- def [](oid)
291
- @mapping[oid]
292
- end
293
-
294
- def clear
295
- @mapping.clear
296
- end
297
-
298
- def key?(oid)
299
- @mapping.key? oid
300
- end
301
-
302
- def fetch(ftype, fmod)
303
- # The type for the numeric depends on the width of the field,
304
- # so we'll do something special here.
305
- #
306
- # When dealing with decimal columns:
307
- #
308
- # places after decimal = fmod - 4 & 0xffff
309
- # places before decimal = (fmod - 4) >> 16 & 0xffff
310
- if ftype == 1700 && (fmod - 4 & 0xffff).zero?
311
- ftype = 23
312
- end
313
-
314
- @mapping.fetch(ftype) { |oid| yield oid, fmod }
315
- end
316
- end
317
-
318
- # When the PG adapter connects, the pg_type table is queried. The
319
- # key of this hash maps to the `typname` column from the table.
320
- # type_map is then dynamically built with oids as the key and type
321
- # objects as values.
322
- NAMES = Hash.new { |h,k| # :nodoc:
323
- h[k] = OID::Identity.new
324
- }
325
-
326
- # Register an OID type named +name+ with a typecasting object in
327
- # +type+. +name+ should correspond to the `typname` column in
328
- # the `pg_type` table.
329
- def self.register_type(name, type)
330
- NAMES[name] = type
331
- end
332
-
333
- # Alias the +old+ type to the +new+ type.
334
- def self.alias_type(new, old)
335
- NAMES[new] = NAMES[old]
336
- end
337
-
338
- # Is +name+ a registered type?
339
- def self.registered_type?(name)
340
- NAMES.key? name
341
- end
342
-
343
- register_type 'int2', OID::Integer.new
344
- alias_type 'int4', 'int2'
345
- alias_type 'int8', 'int2'
346
- alias_type 'oid', 'int2'
347
-
348
- register_type 'daterange', OID::Range.new(:date)
349
- register_type 'numrange', OID::Range.new(:decimal)
350
- register_type 'tsrange', OID::Range.new(:time)
351
- register_type 'int4range', OID::Range.new(:integer)
352
- alias_type 'tstzrange', 'tsrange'
353
- alias_type 'int8range', 'int4range'
354
-
355
- register_type 'numeric', OID::Decimal.new
356
- register_type 'text', OID::Identity.new
357
- alias_type 'varchar', 'text'
358
- alias_type 'char', 'text'
359
- alias_type 'bpchar', 'text'
360
- alias_type 'xml', 'text'
361
-
362
- # FIXME: why are we keeping these types as strings?
363
- alias_type 'tsvector', 'text'
364
- alias_type 'interval', 'text'
365
- alias_type 'macaddr', 'text'
366
- alias_type 'uuid', 'text'
367
-
368
- register_type 'money', OID::Money.new
369
- register_type 'bytea', OID::Bytea.new
370
- register_type 'bool', OID::Boolean.new
371
- register_type 'bit', OID::Bit.new
372
- register_type 'varbit', OID::Bit.new
373
-
374
- register_type 'float4', OID::Float.new
375
- alias_type 'float8', 'float4'
376
-
377
- register_type 'timestamp', OID::Timestamp.new
378
- register_type 'timestamptz', OID::Timestamp.new
379
- register_type 'date', OID::Date.new
380
- register_type 'time', OID::Time.new
381
-
382
- register_type 'path', OID::Identity.new
383
- register_type 'point', OID::Point.new
384
- register_type 'polygon', OID::Identity.new
385
- register_type 'circle', OID::Identity.new
386
- register_type 'hstore', OID::Hstore.new
387
- register_type 'json', OID::Json.new
388
- register_type 'ltree', OID::Identity.new
389
-
390
- register_type 'cidr', OID::Cidr.new
391
- alias_type 'inet', 'cidr'
31
+ module PostgreSQL
32
+ module OID # :nodoc:
392
33
  end
393
34
  end
394
35
  end
@@ -1,142 +1,35 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
- class PostgreSQLAdapter < AbstractAdapter
3
+ module PostgreSQL
4
4
  module Quoting
5
5
  # Escapes binary strings for bytea input to the database.
6
6
  def escape_bytea(value)
7
- PGconn.escape_bytea(value) if value
7
+ @connection.escape_bytea(value) if value
8
8
  end
9
9
 
10
10
  # Unescapes bytea output from a database to the binary string it represents.
11
11
  # NOTE: This is NOT an inverse of escape_bytea! This is only to be used
12
12
  # on escaped binary output from database drive.
13
13
  def unescape_bytea(value)
14
- PGconn.unescape_bytea(value) if value
14
+ @connection.unescape_bytea(value) if value
15
15
  end
16
16
 
17
17
  # Quotes PostgreSQL-specific data types for SQL input.
18
18
  def quote(value, column = nil) #:nodoc:
19
- return super unless column && column.type
20
-
21
- sql_type = type_to_sql(column.type, column.limit, column.precision, column.scale)
19
+ return super unless column
22
20
 
23
21
  case value
24
- when Range
25
- if /range$/ =~ sql_type
26
- escaped = quote_string(PostgreSQLColumn.range_to_string(value))
27
- "'#{escaped}'::#{sql_type}"
28
- else
29
- super
30
- end
31
- when Array
32
- case sql_type
33
- when 'point' then super(PostgreSQLColumn.point_to_string(value))
34
- when 'json' then super(PostgreSQLColumn.json_to_string(value))
35
- else
36
- if column.array
37
- "'#{PostgreSQLColumn.array_to_string(value, column, self).gsub(/'/, "''")}'"
38
- else
39
- super
40
- end
41
- end
42
- when Hash
43
- case sql_type
44
- when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column)
45
- when 'json' then super(PostgreSQLColumn.json_to_string(value), column)
46
- else super
47
- end
48
- when IPAddr
49
- case sql_type
50
- when 'inet', 'cidr' then super(PostgreSQLColumn.cidr_to_string(value), column)
51
- else super
52
- end
53
22
  when Float
54
- if value.infinite? && column.type == :datetime
55
- "'#{value.to_s.downcase}'"
56
- elsif value.infinite? || value.nan?
23
+ if value.infinite? || value.nan?
57
24
  "'#{value.to_s}'"
58
25
  else
59
26
  super
60
27
  end
61
- when Numeric
62
- if sql_type == 'money' || [:string, :text].include?(column.type)
63
- # Not truly string input, so doesn't require (or allow) escape string syntax.
64
- "'#{value}'"
65
- else
66
- super
67
- end
68
- when String
69
- case sql_type
70
- when 'bytea' then "'#{escape_bytea(value)}'"
71
- when 'xml' then "xml '#{quote_string(value)}'"
72
- when /^bit/
73
- case value
74
- when /\A[01]*\Z/ then "B'#{value}'" # Bit-string notation
75
- when /\A[0-9A-F]*\Z/i then "X'#{value}'" # Hexadecimal notation
76
- end
77
- else
78
- super
79
- end
80
28
  else
81
29
  super
82
30
  end
83
31
  end
84
32
 
85
- def type_cast(value, column, array_member = false)
86
- return super(value, column) unless column
87
-
88
- case value
89
- when Range
90
- if /range$/ =~ column.sql_type
91
- PostgreSQLColumn.range_to_string(value)
92
- else
93
- super(value, column)
94
- end
95
- when NilClass
96
- if column.array && array_member
97
- 'NULL'
98
- elsif column.array
99
- value
100
- else
101
- super(value, column)
102
- end
103
- when Array
104
- case column.sql_type
105
- when 'point' then PostgreSQLColumn.point_to_string(value)
106
- when 'json' then PostgreSQLColumn.json_to_string(value)
107
- else
108
- if column.array
109
- PostgreSQLColumn.array_to_string(value, column, self)
110
- else
111
- super(value, column)
112
- end
113
- end
114
- when String
115
- if 'bytea' == column.sql_type
116
- # Return a bind param hash with format as binary.
117
- # See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
118
- # for more information
119
- { value: value, format: 1 }
120
- else
121
- super(value, column)
122
- end
123
- when Hash
124
- case column.sql_type
125
- when 'hstore' then PostgreSQLColumn.hstore_to_string(value, array_member)
126
- when 'json' then PostgreSQLColumn.json_to_string(value)
127
- else super(value, column)
128
- end
129
- when IPAddr
130
- if %w(inet cidr).include? column.sql_type
131
- PostgreSQLColumn.cidr_to_string(value)
132
- else
133
- super(value, column)
134
- end
135
- else
136
- super(value, column)
137
- end
138
- end
139
-
140
33
  # Quotes strings for use in SQL input.
141
34
  def quote_string(s) #:nodoc:
142
35
  @connection.escape(s)
@@ -151,14 +44,7 @@ module ActiveRecord
151
44
  # - "schema.name".table_name
152
45
  # - "schema.name"."table.name"
153
46
  def quote_table_name(name)
154
- schema, name_part = extract_pg_identifier_from_name(name.to_s)
155
-
156
- unless name_part
157
- quote_column_name(schema)
158
- else
159
- table_name, name_part = extract_pg_identifier_from_name(name_part)
160
- "#{quote_column_name(schema)}.#{quote_column_name(table_name)}"
161
- end
47
+ Utils.extract_schema_qualified_name(name.to_s).quoted
162
48
  end
163
49
 
164
50
  def quote_table_name_for_assignment(table, attr)
@@ -178,8 +64,9 @@ module ActiveRecord
178
64
  result = "#{result}.#{sprintf("%06d", value.usec)}"
179
65
  end
180
66
 
181
- if value.year < 0
182
- result = result.sub(/^-/, "") + " BC"
67
+ if value.year <= 0
68
+ bce_year = format("%04d", -value.year + 1)
69
+ result = result.sub(/^-?\d+/, bce_year) + " BC"
183
70
  end
184
71
  result
185
72
  end
@@ -192,6 +79,39 @@ module ActiveRecord
192
79
  quote(value, column)
193
80
  end
194
81
  end
82
+
83
+ private
84
+
85
+ def _quote(value)
86
+ case value
87
+ when Type::Binary::Data
88
+ "'#{escape_bytea(value.to_s)}'"
89
+ when OID::Xml::Data
90
+ "xml '#{quote_string(value.to_s)}'"
91
+ when OID::Bit::Data
92
+ if value.binary?
93
+ "B'#{value}'"
94
+ elsif value.hex?
95
+ "X'#{value}'"
96
+ end
97
+ else
98
+ super
99
+ end
100
+ end
101
+
102
+ def _type_cast(value)
103
+ case value
104
+ when Type::Binary::Data
105
+ # Return a bind param hash with format as binary.
106
+ # See http://deveiate.org/code/pg/PGconn.html#method-i-exec_prepared-doc
107
+ # for more information
108
+ { value: value.to_s, format: 1 }
109
+ when OID::Xml::Data, OID::Bit::Data
110
+ value.to_s
111
+ else
112
+ super
113
+ end
114
+ end
195
115
  end
196
116
  end
197
117
  end
@@ -1,12 +1,12 @@
1
1
  module ActiveRecord
2
2
  module ConnectionAdapters
3
- class PostgreSQLAdapter < AbstractAdapter
4
- module ReferentialIntegrity
5
- def supports_disable_referential_integrity? #:nodoc:
3
+ module PostgreSQL
4
+ module ReferentialIntegrity # :nodoc:
5
+ def supports_disable_referential_integrity? # :nodoc:
6
6
  true
7
7
  end
8
8
 
9
- def disable_referential_integrity #:nodoc:
9
+ def disable_referential_integrity # :nodoc:
10
10
  if supports_disable_referential_integrity?
11
11
  begin
12
12
  execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))