activerecord 4.2.11.1 → 5.0.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 (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1282 -1195
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record.rb +8 -4
  8. data/lib/active_record/aggregations.rb +35 -24
  9. data/lib/active_record/association_relation.rb +3 -3
  10. data/lib/active_record/associations.rb +317 -209
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +11 -9
  13. data/lib/active_record/associations/association_scope.rb +73 -102
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  22. data/lib/active_record/associations/collection_association.rb +49 -41
  23. data/lib/active_record/associations/collection_proxy.rb +67 -27
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +20 -71
  26. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +29 -19
  29. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  30. data/lib/active_record/associations/preloader.rb +14 -4
  31. data/lib/active_record/associations/preloader/association.rb +46 -52
  32. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  33. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  35. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  36. data/lib/active_record/associations/singular_association.rb +7 -1
  37. data/lib/active_record/associations/through_association.rb +11 -3
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  40. data/lib/active_record/attribute_assignment.rb +19 -140
  41. data/lib/active_record/attribute_decorators.rb +6 -5
  42. data/lib/active_record/attribute_methods.rb +76 -47
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  44. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  45. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  46. data/lib/active_record/attribute_methods/query.rb +2 -2
  47. data/lib/active_record/attribute_methods/read.rb +31 -59
  48. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  50. data/lib/active_record/attribute_methods/write.rb +13 -37
  51. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attribute_set/builder.rb +6 -4
  54. data/lib/active_record/attributes.rb +199 -81
  55. data/lib/active_record/autosave_association.rb +49 -16
  56. data/lib/active_record/base.rb +32 -23
  57. data/lib/active_record/callbacks.rb +39 -43
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +20 -8
  60. data/lib/active_record/collection_cache_key.rb +40 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  62. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  63. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  64. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  65. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  66. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  67. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  68. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  69. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  70. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  71. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  72. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  73. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  74. data/lib/active_record/connection_adapters/column.rb +28 -43
  75. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  76. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  77. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  78. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  79. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  80. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  84. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  85. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  88. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  91. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +37 -14
  121. data/lib/active_record/core.rb +89 -107
  122. data/lib/active_record/counter_cache.rb +13 -24
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +113 -76
  125. data/lib/active_record/errors.rb +87 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +76 -40
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +15 -15
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration.rb +363 -133
  140. data/lib/active_record/migration/command_recorder.rb +59 -18
  141. data/lib/active_record/migration/compatibility.rb +126 -0
  142. data/lib/active_record/model_schema.rb +129 -41
  143. data/lib/active_record/nested_attributes.rb +58 -29
  144. data/lib/active_record/null_relation.rb +16 -8
  145. data/lib/active_record/persistence.rb +121 -80
  146. data/lib/active_record/query_cache.rb +15 -18
  147. data/lib/active_record/querying.rb +10 -9
  148. data/lib/active_record/railtie.rb +23 -16
  149. data/lib/active_record/railties/controller_runtime.rb +1 -1
  150. data/lib/active_record/railties/databases.rake +69 -46
  151. data/lib/active_record/readonly_attributes.rb +1 -1
  152. data/lib/active_record/reflection.rb +282 -115
  153. data/lib/active_record/relation.rb +176 -116
  154. data/lib/active_record/relation/batches.rb +139 -34
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  156. data/lib/active_record/relation/calculations.rb +79 -108
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +163 -81
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +16 -42
  161. data/lib/active_record/relation/predicate_builder.rb +120 -107
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  163. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  164. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  166. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  167. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  168. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  169. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +308 -244
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +4 -7
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/result.rb +4 -3
  177. data/lib/active_record/runtime_registry.rb +1 -1
  178. data/lib/active_record/sanitization.rb +95 -66
  179. data/lib/active_record/schema.rb +26 -22
  180. data/lib/active_record/schema_dumper.rb +62 -38
  181. data/lib/active_record/schema_migration.rb +11 -14
  182. data/lib/active_record/scoping.rb +32 -15
  183. data/lib/active_record/scoping/default.rb +23 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/secure_token.rb +38 -0
  186. data/lib/active_record/serialization.rb +2 -4
  187. data/lib/active_record/statement_cache.rb +16 -14
  188. data/lib/active_record/store.rb +8 -3
  189. data/lib/active_record/suppressor.rb +58 -0
  190. data/lib/active_record/table_metadata.rb +68 -0
  191. data/lib/active_record/tasks/database_tasks.rb +57 -43
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  194. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  195. data/lib/active_record/timestamp.rb +20 -9
  196. data/lib/active_record/touch_later.rb +58 -0
  197. data/lib/active_record/transactions.rb +138 -56
  198. data/lib/active_record/type.rb +66 -17
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -45
  201. data/lib/active_record/type/date_time.rb +2 -49
  202. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  203. data/lib/active_record/type/internal/timezone.rb +15 -0
  204. data/lib/active_record/type/serialized.rb +15 -14
  205. data/lib/active_record/type/time.rb +10 -16
  206. data/lib/active_record/type/type_map.rb +4 -4
  207. data/lib/active_record/type_caster.rb +7 -0
  208. data/lib/active_record/type_caster/connection.rb +29 -0
  209. data/lib/active_record/type_caster/map.rb +19 -0
  210. data/lib/active_record/validations.rb +33 -32
  211. data/lib/active_record/validations/absence.rb +23 -0
  212. data/lib/active_record/validations/associated.rb +10 -3
  213. data/lib/active_record/validations/length.rb +24 -0
  214. data/lib/active_record/validations/presence.rb +11 -12
  215. data/lib/active_record/validations/uniqueness.rb +30 -29
  216. data/lib/rails/generators/active_record/migration.rb +7 -0
  217. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  218. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  219. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -110
@@ -2,32 +2,7 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
- class Json < Type::Value # :nodoc:
6
- include Type::Mutable
7
-
8
- def type
9
- :json
10
- end
11
-
12
- def type_cast_from_database(value)
13
- if value.is_a?(::String)
14
- ::ActiveSupport::JSON.decode(value) rescue nil
15
- else
16
- super
17
- end
18
- end
19
-
20
- def type_cast_for_database(value)
21
- if value.is_a?(::Array) || value.is_a?(::Hash)
22
- ::ActiveSupport::JSON.encode(value)
23
- else
24
- super
25
- end
26
- end
27
-
28
- def accessor
29
- ActiveRecord::Store::StringKeyedHashAccessor
30
- end
5
+ class Json < Type::Internal::AbstractJson
31
6
  end
32
7
  end
33
8
  end
@@ -9,11 +9,11 @@ module ActiveRecord
9
9
 
10
10
  def changed_in_place?(raw_old_value, new_value)
11
11
  # Postgres does not preserve insignificant whitespaces when
12
- # roundtripping jsonb columns. This causes some false positives for
12
+ # round-tripping jsonb columns. This causes some false positives for
13
13
  # the comparison here. Therefore, we need to parse and re-dump the
14
14
  # raw value here to ensure the insignificant whitespaces are
15
15
  # consistent with our encoder's output.
16
- raw_old_value = type_cast_for_database(type_cast_from_database(raw_old_value))
16
+ raw_old_value = serialize(deserialize(raw_old_value))
17
17
  super(raw_old_value, new_value)
18
18
  end
19
19
  end
@@ -3,10 +3,6 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Money < Type::Decimal # :nodoc:
6
- include Infinity
7
-
8
- class_attribute :precision
9
-
10
6
  def type
11
7
  :money
12
8
  end
@@ -3,19 +3,19 @@ module ActiveRecord
3
3
  module PostgreSQL
4
4
  module OID # :nodoc:
5
5
  class Point < Type::Value # :nodoc:
6
- include Type::Mutable
6
+ include Type::Helpers::Mutable
7
7
 
8
8
  def type
9
9
  :point
10
10
  end
11
11
 
12
- def type_cast(value)
12
+ def cast(value)
13
13
  case value
14
14
  when ::String
15
15
  if value[0] == '(' && value[-1] == ')'
16
16
  value = value[1...-1]
17
17
  end
18
- type_cast(value.split(','))
18
+ cast(value.split(','))
19
19
  when ::Array
20
20
  value.map { |v| Float(v) }
21
21
  else
@@ -23,7 +23,7 @@ module ActiveRecord
23
23
  end
24
24
  end
25
25
 
26
- def type_cast_for_database(value)
26
+ def serialize(value)
27
27
  if value.is_a?(::Array)
28
28
  "(#{number_for_point(value[0])},#{number_for_point(value[1])})"
29
29
  else
@@ -0,0 +1,50 @@
1
+ module ActiveRecord
2
+ Point = Struct.new(:x, :y)
3
+
4
+ module ConnectionAdapters
5
+ module PostgreSQL
6
+ module OID # :nodoc:
7
+ class Rails51Point < Type::Value # :nodoc:
8
+ include Type::Helpers::Mutable
9
+
10
+ def type
11
+ :point
12
+ end
13
+
14
+ def cast(value)
15
+ case value
16
+ when ::String
17
+ if value[0] == '(' && value[-1] == ')'
18
+ value = value[1...-1]
19
+ end
20
+ x, y = value.split(",")
21
+ build_point(x, y)
22
+ when ::Array
23
+ build_point(*value)
24
+ else
25
+ value
26
+ end
27
+ end
28
+
29
+ def serialize(value)
30
+ if value.is_a?(ActiveRecord::Point)
31
+ "(#{number_for_point(value.x)},#{number_for_point(value.y)})"
32
+ else
33
+ super
34
+ end
35
+ end
36
+
37
+ private
38
+
39
+ def number_for_point(number)
40
+ number.to_s.gsub(/\.0$/, '')
41
+ end
42
+
43
+ def build_point(x, y)
44
+ ActiveRecord::Point.new(Float(x), Float(y))
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -6,8 +6,9 @@ module ActiveRecord
6
6
  module OID # :nodoc:
7
7
  class Range < Type::Value # :nodoc:
8
8
  attr_reader :subtype, :type
9
+ delegate :user_input_in_time_zone, to: :subtype
9
10
 
10
- def initialize(subtype, type)
11
+ def initialize(subtype, type = :range)
11
12
  @subtype = subtype
12
13
  @type = type
13
14
  end
@@ -18,28 +19,19 @@ module ActiveRecord
18
19
 
19
20
  def cast_value(value)
20
21
  return if value == 'empty'
21
- return value if value.is_a?(::Range)
22
+ return value unless value.is_a?(::String)
22
23
 
23
24
  extracted = extract_bounds(value)
24
25
  from = type_cast_single extracted[:from]
25
26
  to = type_cast_single extracted[:to]
26
27
 
27
28
  if !infinity?(from) && extracted[:exclude_start]
28
- if from.respond_to?(:succ)
29
- from = from.succ
30
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
31
- Excluding the beginning of a Range is only partialy supported
32
- through `#succ`. This is not reliable and will be removed in
33
- the future.
34
- MSG
35
- else
36
- raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
37
- end
29
+ raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')"
38
30
  end
39
31
  ::Range.new(from, to, extracted[:exclude_end])
40
32
  end
41
33
 
42
- def type_cast_for_database(value)
34
+ def serialize(value)
43
35
  if value.is_a?(::Range)
44
36
  from = type_cast_single_for_database(value.begin)
45
37
  to = type_cast_single_for_database(value.end)
@@ -49,26 +41,48 @@ module ActiveRecord
49
41
  end
50
42
  end
51
43
 
44
+ def ==(other)
45
+ other.is_a?(Range) &&
46
+ other.subtype == subtype &&
47
+ other.type == type
48
+ end
49
+
50
+ def map(value) # :nodoc:
51
+ new_begin = yield(value.begin)
52
+ new_end = yield(value.end)
53
+ ::Range.new(new_begin, new_end, value.exclude_end?)
54
+ end
55
+
52
56
  private
53
57
 
54
58
  def type_cast_single(value)
55
- infinity?(value) ? value : @subtype.type_cast_from_database(value)
59
+ infinity?(value) ? value : @subtype.deserialize(value)
56
60
  end
57
61
 
58
62
  def type_cast_single_for_database(value)
59
- infinity?(value) ? '' : @subtype.type_cast_for_database(value)
63
+ infinity?(value) ? '' : @subtype.serialize(value)
60
64
  end
61
65
 
62
66
  def extract_bounds(value)
63
67
  from, to = value[1..-2].split(',')
64
68
  {
65
- from: (value[1] == ',' || from == '-infinity') ? @subtype.infinity(negative: true) : from,
66
- to: (value[-2] == ',' || to == 'infinity') ? @subtype.infinity : to,
69
+ from: (value[1] == ',' || from == '-infinity') ? infinity(negative: true) : from,
70
+ to: (value[-2] == ',' || to == 'infinity') ? infinity : to,
67
71
  exclude_start: (value[0] == '('),
68
72
  exclude_end: (value[-1] == ')')
69
73
  }
70
74
  end
71
75
 
76
+ def infinity(negative: false)
77
+ if subtype.respond_to?(:infinity)
78
+ subtype.infinity(negative: negative)
79
+ elsif negative
80
+ -::Float::INFINITY
81
+ else
82
+ ::Float::INFINITY
83
+ end
84
+ end
85
+
72
86
  def infinity?(value)
73
87
  value.respond_to?(:infinite?) && value.infinite?
74
88
  end
@@ -8,10 +8,6 @@ module ActiveRecord
8
8
  def initialize(type)
9
9
  @type = type
10
10
  end
11
-
12
- def text?
13
- false
14
- end
15
11
  end
16
12
  end
17
13
  end
@@ -5,13 +5,13 @@ module ActiveRecord
5
5
  class Uuid < Type::Value # :nodoc:
6
6
  ACCEPTABLE_UUID = %r{\A\{?([a-fA-F0-9]{4}-?){8}\}?\z}x
7
7
 
8
- alias_method :type_cast_for_database, :type_cast_from_database
8
+ alias_method :serialize, :deserialize
9
9
 
10
10
  def type
11
11
  :uuid
12
12
  end
13
13
 
14
- def type_cast(value)
14
+ def cast(value)
15
15
  value.to_s[ACCEPTABLE_UUID, 0]
16
16
  end
17
17
  end
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  # FIXME: this should probably split on +delim+ and use +subtype+
17
17
  # to cast the values. Unfortunately, the current Rails behavior
18
18
  # is to just return the string.
19
- def type_cast(value)
19
+ def cast(value)
20
20
  value
21
21
  end
22
22
  end
@@ -7,7 +7,7 @@ module ActiveRecord
7
7
  :xml
8
8
  end
9
9
 
10
- def type_cast_for_database(value)
10
+ def serialize(value)
11
11
  return unless value
12
12
  Data.new(super)
13
13
  end
@@ -27,8 +27,13 @@ module ActiveRecord
27
27
  # - schema_name."table.name"
28
28
  # - "schema.name".table_name
29
29
  # - "schema.name"."table.name"
30
- def quote_table_name(name)
31
- Utils.extract_schema_qualified_name(name.to_s).quoted
30
+ def quote_table_name(name) # :nodoc:
31
+ @quoted_table_names[name] ||= Utils.extract_schema_qualified_name(name.to_s).quoted
32
+ end
33
+
34
+ # Quotes schema names for use in SQL queries.
35
+ def quote_schema_name(name)
36
+ PGconn.quote_ident(name)
32
37
  end
33
38
 
34
39
  def quote_table_name_for_assignment(table, attr)
@@ -36,34 +41,37 @@ module ActiveRecord
36
41
  end
37
42
 
38
43
  # Quotes column names for use in SQL queries.
39
- def quote_column_name(name) #:nodoc:
40
- PGconn.quote_ident(name.to_s)
44
+ def quote_column_name(name) # :nodoc:
45
+ @quoted_column_names[name] ||= PGconn.quote_ident(super)
41
46
  end
42
47
 
43
- # Quote date/time values for use in SQL input. Includes microseconds
44
- # if the value is a Time responding to usec.
48
+ # Quote date/time values for use in SQL input.
45
49
  def quoted_date(value) #:nodoc:
46
- result = super
47
- if value.acts_like?(:time) && value.respond_to?(:usec)
48
- result = "#{result}.#{sprintf("%06d", value.usec)}"
49
- end
50
-
51
50
  if value.year <= 0
52
51
  bce_year = format("%04d", -value.year + 1)
53
- result = result.sub(/^-?\d+/, bce_year) + " BC"
52
+ super.sub(/^-?\d+/, bce_year) + " BC"
53
+ else
54
+ super
54
55
  end
55
- result
56
56
  end
57
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
58
+ def quote_default_expression(value, column) # :nodoc:
59
+ if value.is_a?(Proc)
60
+ value.call
61
+ elsif column.type == :uuid && value =~ /\(\)/
62
+ value # Does not quote function default values for UUID columns
63
+ elsif column.respond_to?(:array?)
64
+ value = type_cast_from_column(column, value)
65
+ quote(value)
62
66
  else
63
- quote(value, column)
67
+ super
64
68
  end
65
69
  end
66
70
 
71
+ def lookup_cast_type_from_column(column) # :nodoc:
72
+ type_map.lookup(column.oid, column.fmod, column.sql_type)
73
+ end
74
+
67
75
  private
68
76
 
69
77
  def _quote(value)
@@ -8,20 +8,39 @@ module ActiveRecord
8
8
 
9
9
  def disable_referential_integrity # :nodoc:
10
10
  if supports_disable_referential_integrity?
11
+ original_exception = nil
12
+
11
13
  begin
12
- execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
13
- rescue
14
- execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER USER" }.join(";"))
14
+ transaction(requires_new: true) do
15
+ execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
16
+ end
17
+ rescue ActiveRecord::ActiveRecordError => e
18
+ original_exception = e
15
19
  end
16
- end
17
- yield
18
- ensure
19
- if supports_disable_referential_integrity?
20
+
21
+ begin
22
+ yield
23
+ rescue ActiveRecord::InvalidForeignKey => e
24
+ warn <<-WARNING
25
+ WARNING: Rails was not able to disable referential integrity.
26
+
27
+ This is most likely caused due to missing permissions.
28
+ Rails needs superuser privileges to disable referential integrity.
29
+
30
+ cause: #{original_exception.try(:message)}
31
+
32
+ WARNING
33
+ raise e
34
+ end
35
+
20
36
  begin
21
- execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
22
- rescue
23
- execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER USER" }.join(";"))
37
+ transaction(requires_new: true) do
38
+ execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
39
+ end
40
+ rescue ActiveRecord::ActiveRecordError
24
41
  end
42
+ else
43
+ yield
25
44
  end
26
45
  end
27
46
  end
@@ -2,90 +2,153 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  module PostgreSQL
4
4
  module ColumnMethods
5
- def xml(*args)
6
- options = args.extract_options!
7
- column(args[0], :xml, options)
5
+ # Defines the primary key field.
6
+ # Use of the native PostgreSQL UUID type is supported, and can be used
7
+ # by defining your tables as such:
8
+ #
9
+ # create_table :stuffs, id: :uuid do |t|
10
+ # t.string :content
11
+ # t.timestamps
12
+ # end
13
+ #
14
+ # By default, this will use the +uuid_generate_v4()+ function from the
15
+ # +uuid-ossp+ extension, which MUST be enabled on your database. To enable
16
+ # the +uuid-ossp+ extension, you can use the +enable_extension+ method in your
17
+ # migrations. To use a UUID primary key without +uuid-ossp+ enabled, you can
18
+ # set the +:default+ option to +nil+:
19
+ #
20
+ # create_table :stuffs, id: false do |t|
21
+ # t.primary_key :id, :uuid, default: nil
22
+ # t.uuid :foo_id
23
+ # t.timestamps
24
+ # end
25
+ #
26
+ # You may also pass a different UUID generation function from +uuid-ossp+
27
+ # or another library.
28
+ #
29
+ # Note that setting the UUID primary key default value to +nil+ will
30
+ # require you to assure that you always provide a UUID value before saving
31
+ # a record (as primary keys cannot be +nil+). This might be done via the
32
+ # +SecureRandom.uuid+ method and a +before_save+ callback, for instance.
33
+ def primary_key(name, type = :primary_key, **options)
34
+ options[:default] = options.fetch(:default, 'uuid_generate_v4()') if type == :uuid
35
+ super
36
+ end
37
+
38
+ def bigserial(*args, **options)
39
+ args.each { |name| column(name, :bigserial, options) }
40
+ end
41
+
42
+ def bit(*args, **options)
43
+ args.each { |name| column(name, :bit, options) }
44
+ end
45
+
46
+ def bit_varying(*args, **options)
47
+ args.each { |name| column(name, :bit_varying, options) }
48
+ end
49
+
50
+ def cidr(*args, **options)
51
+ args.each { |name| column(name, :cidr, options) }
52
+ end
53
+
54
+ def citext(*args, **options)
55
+ args.each { |name| column(name, :citext, options) }
8
56
  end
9
57
 
10
- def tsvector(*args)
11
- options = args.extract_options!
12
- column(args[0], :tsvector, options)
58
+ def daterange(*args, **options)
59
+ args.each { |name| column(name, :daterange, options) }
13
60
  end
14
61
 
15
- def int4range(name, options = {})
16
- column(name, :int4range, options)
62
+ def hstore(*args, **options)
63
+ args.each { |name| column(name, :hstore, options) }
17
64
  end
18
65
 
19
- def int8range(name, options = {})
20
- column(name, :int8range, options)
66
+ def inet(*args, **options)
67
+ args.each { |name| column(name, :inet, options) }
21
68
  end
22
69
 
23
- def tsrange(name, options = {})
24
- column(name, :tsrange, options)
70
+ def int4range(*args, **options)
71
+ args.each { |name| column(name, :int4range, options) }
25
72
  end
26
73
 
27
- def tstzrange(name, options = {})
28
- column(name, :tstzrange, options)
74
+ def int8range(*args, **options)
75
+ args.each { |name| column(name, :int8range, options) }
29
76
  end
30
77
 
31
- def numrange(name, options = {})
32
- column(name, :numrange, options)
78
+ def json(*args, **options)
79
+ args.each { |name| column(name, :json, options) }
33
80
  end
34
81
 
35
- def daterange(name, options = {})
36
- column(name, :daterange, options)
82
+ def jsonb(*args, **options)
83
+ args.each { |name| column(name, :jsonb, options) }
37
84
  end
38
85
 
39
- def hstore(name, options = {})
40
- column(name, :hstore, options)
86
+ def ltree(*args, **options)
87
+ args.each { |name| column(name, :ltree, options) }
41
88
  end
42
89
 
43
- def ltree(name, options = {})
44
- column(name, :ltree, options)
90
+ def macaddr(*args, **options)
91
+ args.each { |name| column(name, :macaddr, options) }
45
92
  end
46
93
 
47
- def inet(name, options = {})
48
- column(name, :inet, options)
94
+ def money(*args, **options)
95
+ args.each { |name| column(name, :money, options) }
49
96
  end
50
97
 
51
- def cidr(name, options = {})
52
- column(name, :cidr, options)
98
+ def numrange(*args, **options)
99
+ args.each { |name| column(name, :numrange, options) }
53
100
  end
54
101
 
55
- def macaddr(name, options = {})
56
- column(name, :macaddr, options)
102
+ def point(*args, **options)
103
+ args.each { |name| column(name, :point, options) }
57
104
  end
58
105
 
59
- def uuid(name, options = {})
60
- column(name, :uuid, options)
106
+ def line(*args, **options)
107
+ args.each { |name| column(name, :line, options) }
61
108
  end
62
109
 
63
- def json(name, options = {})
64
- column(name, :json, options)
110
+ def lseg(*args, **options)
111
+ args.each { |name| column(name, :lseg, options) }
65
112
  end
66
113
 
67
- def jsonb(name, options = {})
68
- column(name, :jsonb, options)
114
+ def box(*args, **options)
115
+ args.each { |name| column(name, :box, options) }
69
116
  end
70
117
 
71
- def citext(name, options = {})
72
- column(name, :citext, options)
118
+ def path(*args, **options)
119
+ args.each { |name| column(name, :path, options) }
73
120
  end
74
121
 
75
- def point(name, options = {})
76
- column(name, :point, options)
122
+ def polygon(*args, **options)
123
+ args.each { |name| column(name, :polygon, options) }
77
124
  end
78
125
 
79
- def bit(name, options = {})
80
- column(name, :bit, options)
126
+ def circle(*args, **options)
127
+ args.each { |name| column(name, :circle, options) }
81
128
  end
82
129
 
83
- def bit_varying(name, options = {})
84
- column(name, :bit_varying, options)
130
+ def serial(*args, **options)
131
+ args.each { |name| column(name, :serial, options) }
85
132
  end
86
133
 
87
- def money(name, options = {})
88
- column(name, :money, options)
134
+ def tsrange(*args, **options)
135
+ args.each { |name| column(name, :tsrange, options) }
136
+ end
137
+
138
+ def tstzrange(*args, **options)
139
+ args.each { |name| column(name, :tstzrange, options) }
140
+ end
141
+
142
+ def tsvector(*args, **options)
143
+ args.each { |name| column(name, :tsvector, options) }
144
+ end
145
+
146
+ def uuid(*args, **options)
147
+ args.each { |name| column(name, :uuid, options) }
148
+ end
149
+
150
+ def xml(*args, **options)
151
+ args.each { |name| column(name, :xml, options) }
89
152
  end
90
153
  end
91
154
 
@@ -96,41 +159,6 @@ module ActiveRecord
96
159
  class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
97
160
  include ColumnMethods
98
161
 
99
- # Defines the primary key field.
100
- # Use of the native PostgreSQL UUID type is supported, and can be used
101
- # by defining your tables as such:
102
- #
103
- # create_table :stuffs, id: :uuid do |t|
104
- # t.string :content
105
- # t.timestamps
106
- # end
107
- #
108
- # By default, this will use the +uuid_generate_v4()+ function from the
109
- # +uuid-ossp+ extension, which MUST be enabled on your database. To enable
110
- # the +uuid-ossp+ extension, you can use the +enable_extension+ method in your
111
- # migrations. To use a UUID primary key without +uuid-ossp+ enabled, you can
112
- # set the +:default+ option to +nil+:
113
- #
114
- # create_table :stuffs, id: false do |t|
115
- # t.primary_key :id, :uuid, default: nil
116
- # t.uuid :foo_id
117
- # t.timestamps
118
- # end
119
- #
120
- # You may also pass a different UUID generation function from +uuid-ossp+
121
- # or another library.
122
- #
123
- # Note that setting the UUID primary key default value to +nil+ will
124
- # require you to assure that you always provide a UUID value before saving
125
- # a record (as primary keys cannot be +nil+). This might be done via the
126
- # +SecureRandom.uuid+ method and a +before_save+ callback, for instance.
127
- def primary_key(name, type = :primary_key, options = {})
128
- return super unless type == :uuid
129
- options[:default] = options.fetch(:default, 'uuid_generate_v4()')
130
- options[:primary_key] = true
131
- column name, type, options
132
- end
133
-
134
162
  def new_column_definition(name, type, options) # :nodoc:
135
163
  column = super
136
164
  column.array = options[:array]