activerecord 4.1.0 → 4.2.0

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