activerecord 5.1.0 → 5.2.0.rc1

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 (260) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +410 -530
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +23 -32
  10. data/lib/active_record/associations/association.rb +20 -21
  11. data/lib/active_record/associations/association_scope.rb +49 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +12 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -6
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +50 -41
  22. data/lib/active_record/associations/collection_proxy.rb +22 -39
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +4 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +12 -18
  26. data/lib/active_record/associations/has_one_association.rb +5 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +27 -44
  32. data/lib/active_record/associations/preloader/association.rb +53 -92
  33. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -10
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +68 -76
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +24 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +8 -2
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +22 -19
  48. data/lib/active_record/attribute_methods.rb +48 -12
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +14 -10
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
  69. data/lib/active_record/connection_adapters/column.rb +4 -2
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +269 -126
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
  116. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +39 -60
  128. data/lib/active_record/counter_cache.rb +3 -2
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +17 -13
  132. data/lib/active_record/errors.rb +42 -3
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +67 -60
  138. data/lib/active_record/gem_version.rb +4 -2
  139. data/lib/active_record/inheritance.rb +9 -9
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +8 -6
  144. data/lib/active_record/locking/pessimistic.rb +9 -6
  145. data/lib/active_record/log_subscriber.rb +46 -4
  146. data/lib/active_record/migration/command_recorder.rb +11 -9
  147. data/lib/active_record/migration/compatibility.rb +74 -22
  148. data/lib/active_record/migration/join_table.rb +2 -0
  149. data/lib/active_record/migration.rb +181 -137
  150. data/lib/active_record/model_schema.rb +73 -58
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +153 -18
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +4 -2
  157. data/lib/active_record/railtie.rb +61 -3
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +47 -37
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +131 -204
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  164. data/lib/active_record/relation/batches.rb +32 -17
  165. data/lib/active_record/relation/calculations.rb +58 -20
  166. data/lib/active_record/relation/delegation.rb +10 -29
  167. data/lib/active_record/relation/finder_methods.rb +74 -85
  168. data/lib/active_record/relation/from_clause.rb +2 -8
  169. data/lib/active_record/relation/merger.rb +51 -20
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  172. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  173. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  175. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  176. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  177. data/lib/active_record/relation/predicate_builder.rb +53 -78
  178. data/lib/active_record/relation/query_attribute.rb +9 -2
  179. data/lib/active_record/relation/query_methods.rb +101 -95
  180. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  181. data/lib/active_record/relation/spawn_methods.rb +3 -1
  182. data/lib/active_record/relation/where_clause.rb +65 -67
  183. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  184. data/lib/active_record/relation.rb +99 -202
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +129 -121
  188. data/lib/active_record/schema.rb +4 -2
  189. data/lib/active_record/schema_dumper.rb +36 -26
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping/default.rb +10 -7
  192. data/lib/active_record/scoping/named.rb +38 -12
  193. data/lib/active_record/scoping.rb +12 -10
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +3 -1
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +12 -3
  200. data/lib/active_record/tasks/database_tasks.rb +37 -25
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -5
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  209. data/lib/active_record/type/date.rb +2 -0
  210. data/lib/active_record/type/date_time.rb +2 -0
  211. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  212. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  213. data/lib/active_record/type/internal/timezone.rb +2 -0
  214. data/lib/active_record/type/json.rb +30 -0
  215. data/lib/active_record/type/serialized.rb +2 -0
  216. data/lib/active_record/type/text.rb +2 -0
  217. data/lib/active_record/type/time.rb +2 -0
  218. data/lib/active_record/type/type_map.rb +2 -0
  219. data/lib/active_record/type/unsigned_integer.rb +2 -0
  220. data/lib/active_record/type.rb +4 -1
  221. data/lib/active_record/type_caster/connection.rb +2 -0
  222. data/lib/active_record/type_caster/map.rb +3 -1
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/validations/absence.rb +2 -0
  225. data/lib/active_record/validations/associated.rb +2 -0
  226. data/lib/active_record/validations/length.rb +2 -0
  227. data/lib/active_record/validations/presence.rb +2 -0
  228. data/lib/active_record/validations/uniqueness.rb +35 -5
  229. data/lib/active_record/validations.rb +2 -0
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/active_record.rb +11 -4
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  235. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration.rb +2 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record.rb +3 -1
  242. metadata +25 -37
  243. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  244. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  245. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  246. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  247. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  248. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  249. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -124
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/attribute_set.rb +0 -113
  256. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  257. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  258. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  259. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  260. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,63 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/compact"
4
+
1
5
  module ActiveRecord
2
6
  module ConnectionAdapters # :nodoc:
3
- # The goal of this module is to move Adapter specific column
4
- # definitions to the Adapter instead of having it in the schema
5
- # dumper itself. This code represents the normal case.
6
- # We can then redefine how certain data types may be handled in the schema dumper on the
7
- # Adapter level by over-writing this code inside the database specific adapters
8
- module ColumnDumper
9
- def column_spec(column)
10
- [schema_type_with_virtual(column), prepare_column_options(column)]
7
+ class SchemaDumper < SchemaDumper # :nodoc:
8
+ def self.create(connection, options)
9
+ new(connection, options)
11
10
  end
12
11
 
13
- def column_spec_for_primary_key(column)
14
- return {} if default_primary_key?(column)
15
- spec = { id: schema_type(column).inspect }
16
- spec.merge!(prepare_column_options(column).except!(:null))
17
- spec[:default] ||= "nil" if explicit_primary_key_default?(column)
18
- spec
19
- end
20
-
21
- # This can be overridden on an Adapter level basis to support other
22
- # extended datatypes (Example: Adding an array option in the
23
- # PostgreSQL::ColumnDumper)
24
- def prepare_column_options(column)
25
- spec = {}
26
-
27
- if limit = schema_limit(column)
28
- spec[:limit] = limit
12
+ private
13
+ def column_spec(column)
14
+ [schema_type_with_virtual(column), prepare_column_options(column)]
29
15
  end
30
16
 
31
- if precision = schema_precision(column)
32
- spec[:precision] = precision
17
+ def column_spec_for_primary_key(column)
18
+ return {} if default_primary_key?(column)
19
+ spec = { id: schema_type(column).inspect }
20
+ spec.merge!(prepare_column_options(column).except!(:null))
21
+ spec[:default] ||= "nil" if explicit_primary_key_default?(column)
22
+ spec
33
23
  end
34
24
 
35
- if scale = schema_scale(column)
36
- spec[:scale] = scale
25
+ def prepare_column_options(column)
26
+ spec = {}
27
+ spec[:limit] = schema_limit(column)
28
+ spec[:precision] = schema_precision(column)
29
+ spec[:scale] = schema_scale(column)
30
+ spec[:default] = schema_default(column)
31
+ spec[:null] = "false" unless column.null
32
+ spec[:collation] = schema_collation(column)
33
+ spec[:comment] = column.comment.inspect if column.comment.present?
34
+ spec.compact!
35
+ spec
37
36
  end
38
37
 
39
- default = schema_default(column) if column.has_default?
40
- spec[:default] = default unless default.nil?
41
-
42
- spec[:null] = "false" unless column.null
43
-
44
- if collation = schema_collation(column)
45
- spec[:collation] = collation
46
- end
47
-
48
- spec[:comment] = column.comment.inspect if column.comment.present?
49
-
50
- spec
51
- end
52
-
53
- # Lists the valid migration options
54
- def migration_keys # :nodoc:
55
- column_options_keys
56
- end
57
- deprecate :migration_keys
58
-
59
- private
60
-
61
38
  def default_primary_key?(column)
62
39
  schema_type(column) == :bigint
63
40
  end
@@ -67,7 +44,7 @@ module ActiveRecord
67
44
  end
68
45
 
69
46
  def schema_type_with_virtual(column)
70
- if supports_virtual_columns? && column.virtual?
47
+ if @connection.supports_virtual_columns? && column.virtual?
71
48
  :virtual
72
49
  else
73
50
  schema_type(column)
@@ -84,7 +61,7 @@ module ActiveRecord
84
61
 
85
62
  def schema_limit(column)
86
63
  limit = column.limit unless column.bigint?
87
- limit.inspect if limit && limit != native_database_types[column.type][:limit]
64
+ limit.inspect if limit && limit != @connection.native_database_types[column.type][:limit]
88
65
  end
89
66
 
90
67
  def schema_precision(column)
@@ -96,7 +73,8 @@ module ActiveRecord
96
73
  end
97
74
 
98
75
  def schema_default(column)
99
- type = lookup_cast_type_from_column(column)
76
+ return unless column.has_default?
77
+ type = @connection.lookup_cast_type_from_column(column)
100
78
  default = type.deserialize(column.default)
101
79
  if default.nil?
102
80
  schema_expression(column)
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_record/migration/join_table"
2
4
  require "active_support/core_ext/string/access"
3
- require "digest"
5
+ require "digest/sha2"
4
6
 
5
7
  module ActiveRecord
6
8
  module ConnectionAdapters # :nodoc:
@@ -31,7 +33,7 @@ module ActiveRecord
31
33
  # Returns the relation names useable to back Active Record models.
32
34
  # For most adapters this means all #tables and #views.
33
35
  def data_sources
34
- select_values(data_source_sql, "SCHEMA")
36
+ query_values(data_source_sql, "SCHEMA")
35
37
  rescue NotImplementedError
36
38
  tables | views
37
39
  end
@@ -41,14 +43,14 @@ module ActiveRecord
41
43
  # data_source_exists?(:ebooks)
42
44
  #
43
45
  def data_source_exists?(name)
44
- select_values(data_source_sql(name), "SCHEMA").any? if name.present?
46
+ query_values(data_source_sql(name), "SCHEMA").any? if name.present?
45
47
  rescue NotImplementedError
46
48
  data_sources.include?(name.to_s)
47
49
  end
48
50
 
49
51
  # Returns an array of table names defined in the database.
50
52
  def tables
51
- select_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
53
+ query_values(data_source_sql(type: "BASE TABLE"), "SCHEMA")
52
54
  end
53
55
 
54
56
  # Checks to see if the table +table_name+ exists on the database.
@@ -56,14 +58,14 @@ module ActiveRecord
56
58
  # table_exists?(:developers)
57
59
  #
58
60
  def table_exists?(table_name)
59
- select_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
61
+ query_values(data_source_sql(table_name, type: "BASE TABLE"), "SCHEMA").any? if table_name.present?
60
62
  rescue NotImplementedError
61
63
  tables.include?(table_name.to_s)
62
64
  end
63
65
 
64
66
  # Returns an array of view names defined in the database.
65
67
  def views
66
- select_values(data_source_sql(type: "VIEW"), "SCHEMA")
68
+ query_values(data_source_sql(type: "VIEW"), "SCHEMA")
67
69
  end
68
70
 
69
71
  # Checks to see if the view +view_name+ exists on the database.
@@ -71,13 +73,13 @@ module ActiveRecord
71
73
  # view_exists?(:ebooks)
72
74
  #
73
75
  def view_exists?(view_name)
74
- select_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
76
+ query_values(data_source_sql(view_name, type: "VIEW"), "SCHEMA").any? if view_name.present?
75
77
  rescue NotImplementedError
76
78
  views.include?(view_name.to_s)
77
79
  end
78
80
 
79
81
  # Returns an array of indexes for the given table.
80
- def indexes(table_name, name = nil)
82
+ def indexes(table_name)
81
83
  raise NotImplementedError, "#indexes is not implemented"
82
84
  end
83
85
 
@@ -105,10 +107,12 @@ module ActiveRecord
105
107
  indexes(table_name).any? { |i| checks.all? { |check| check[i] } }
106
108
  end
107
109
 
108
- # Returns an array of Column objects for the table specified by +table_name+.
109
- # See the concrete implementation for details on the expected parameter values.
110
+ # Returns an array of +Column+ objects for the table specified by +table_name+.
110
111
  def columns(table_name)
111
- raise NotImplementedError, "#columns is not implemented"
112
+ table_name = table_name.to_s
113
+ column_definitions(table_name).map do |field|
114
+ new_column_from_field(table_name, field)
115
+ end
112
116
  end
113
117
 
114
118
  # Checks to see if a column exists in a given table.
@@ -186,6 +190,8 @@ module ActiveRecord
186
190
  # The name of the primary key, if one is to be added automatically.
187
191
  # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored.
188
192
  #
193
+ # If an array is passed, a composite primary key will be created.
194
+ #
189
195
  # Note that Active Record models will automatically detect their
190
196
  # primary key. This can be avoided by using
191
197
  # {self.primary_key=}[rdoc-ref:AttributeMethods::PrimaryKey::ClassMethods#primary_key=] on the model
@@ -210,7 +216,7 @@ module ActiveRecord
210
216
  # generates:
211
217
  #
212
218
  # CREATE TABLE suppliers (
213
- # id int auto_increment PRIMARY KEY
219
+ # id bigint auto_increment PRIMARY KEY
214
220
  # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
215
221
  #
216
222
  # ====== Rename the primary key column
@@ -222,7 +228,7 @@ module ActiveRecord
222
228
  # generates:
223
229
  #
224
230
  # CREATE TABLE objects (
225
- # guid int auto_increment PRIMARY KEY,
231
+ # guid bigint auto_increment PRIMARY KEY,
226
232
  # name varchar(80)
227
233
  # )
228
234
  #
@@ -239,18 +245,35 @@ module ActiveRecord
239
245
  # label varchar
240
246
  # )
241
247
  #
248
+ # ====== Create a composite primary key
249
+ #
250
+ # create_table(:orders, primary_key: [:product_id, :client_id]) do |t|
251
+ # t.belongs_to :product
252
+ # t.belongs_to :client
253
+ # end
254
+ #
255
+ # generates:
256
+ #
257
+ # CREATE TABLE order (
258
+ # product_id bigint NOT NULL,
259
+ # client_id bigint NOT NULL
260
+ # );
261
+ #
262
+ # ALTER TABLE ONLY "orders"
263
+ # ADD CONSTRAINT orders_pkey PRIMARY KEY (product_id, client_id);
264
+ #
242
265
  # ====== Do not add a primary key column
243
266
  #
244
267
  # create_table(:categories_suppliers, id: false) do |t|
245
- # t.column :category_id, :integer
246
- # t.column :supplier_id, :integer
268
+ # t.column :category_id, :bigint
269
+ # t.column :supplier_id, :bigint
247
270
  # end
248
271
  #
249
272
  # generates:
250
273
  #
251
274
  # CREATE TABLE categories_suppliers (
252
- # category_id int,
253
- # supplier_id int
275
+ # category_id bigint,
276
+ # supplier_id bigint
254
277
  # )
255
278
  #
256
279
  # ====== Create a temporary table based on a query
@@ -338,8 +361,8 @@ module ActiveRecord
338
361
  # generates:
339
362
  #
340
363
  # CREATE TABLE assemblies_parts (
341
- # assembly_id int NOT NULL,
342
- # part_id int NOT NULL,
364
+ # assembly_id bigint NOT NULL,
365
+ # part_id bigint NOT NULL,
343
366
  # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
344
367
  #
345
368
  def create_join_table(table_1, table_2, column_options: {}, **options)
@@ -383,6 +406,8 @@ module ActiveRecord
383
406
  #
384
407
  # Defaults to false.
385
408
  #
409
+ # Only supported on the MySQL adapter, ignored elsewhere.
410
+ #
386
411
  # ====== Add a column
387
412
  #
388
413
  # change_table(:suppliers) do |t|
@@ -407,7 +432,7 @@ module ActiveRecord
407
432
  # t.references :company
408
433
  # end
409
434
  #
410
- # Creates a <tt>company_id(integer)</tt> column.
435
+ # Creates a <tt>company_id(bigint)</tt> column.
411
436
  #
412
437
  # ====== Add a polymorphic foreign key column
413
438
  #
@@ -415,7 +440,7 @@ module ActiveRecord
415
440
  # t.belongs_to :company, polymorphic: true
416
441
  # end
417
442
  #
418
- # Creates <tt>company_type(varchar)</tt> and <tt>company_id(integer)</tt> columns.
443
+ # Creates <tt>company_type(varchar)</tt> and <tt>company_id(bigint)</tt> columns.
419
444
  #
420
445
  # ====== Remove a column
421
446
  #
@@ -488,15 +513,17 @@ module ActiveRecord
488
513
  # * <tt>:limit</tt> -
489
514
  # Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
490
515
  # and number of bytes for <tt>:text</tt>, <tt>:binary</tt> and <tt>:integer</tt> columns.
516
+ # This option is ignored by some backends.
491
517
  # * <tt>:default</tt> -
492
518
  # The column's default value. Use +nil+ for +NULL+.
493
519
  # * <tt>:null</tt> -
494
- # Allows or disallows +NULL+ values in the column. This option could
495
- # have been named <tt>:null_allowed</tt>.
520
+ # Allows or disallows +NULL+ values in the column.
496
521
  # * <tt>:precision</tt> -
497
522
  # Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
498
523
  # * <tt>:scale</tt> -
499
524
  # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
525
+ # * <tt>:comment</tt> -
526
+ # Specifies the comment for the column. This option is ignored by some backends.
500
527
  #
501
528
  # Note: The precision is the total number of significant digits,
502
529
  # and the scale is the number of digits that can be stored following
@@ -573,7 +600,7 @@ module ActiveRecord
573
600
  # to provide these in a migration's +change+ method so it can be reverted.
574
601
  # In that case, +type+ and +options+ will be used by #add_column.
575
602
  def remove_column(table_name, column_name, type = nil, options = {})
576
- execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}"
603
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
577
604
  end
578
605
 
579
606
  # Changes the column's definition according to the new options.
@@ -688,7 +715,7 @@ module ActiveRecord
688
715
  #
689
716
  # CREATE INDEX by_branch_desc_party ON accounts(branch_id DESC, party_id ASC, surname)
690
717
  #
691
- # Note: MySQL doesn't yet support index order (it accepts the syntax but ignores it).
718
+ # Note: MySQL only supports index order from 8.0.1 onwards (earlier versions accepted the syntax but ignored it).
692
719
  #
693
720
  # ====== Creating a partial index
694
721
  #
@@ -711,6 +738,28 @@ module ActiveRecord
711
738
  #
712
739
  # Note: only supported by PostgreSQL and MySQL
713
740
  #
741
+ # ====== Creating an index with a specific operator class
742
+ #
743
+ # add_index(:developers, :name, using: 'gist', opclass: :gist_trgm_ops)
744
+ #
745
+ # generates:
746
+ #
747
+ # CREATE INDEX developers_on_name ON developers USING gist (name gist_trgm_ops) -- PostgreSQL
748
+ #
749
+ # add_index(:developers, [:name, :city], using: 'gist', opclass: { city: :gist_trgm_ops })
750
+ #
751
+ # generates:
752
+ #
753
+ # CREATE INDEX developers_on_name_and_city ON developers USING gist (name, city gist_trgm_ops) -- PostgreSQL
754
+ #
755
+ # add_index(:developers, [:name, :city], using: 'gist', opclass: :gist_trgm_ops)
756
+ #
757
+ # generates:
758
+ #
759
+ # CREATE INDEX developers_on_name_and_city ON developers USING gist (name gist_trgm_ops, city gist_trgm_ops) -- PostgreSQL
760
+ #
761
+ # Note: only supported by PostgreSQL
762
+ #
714
763
  # ====== Creating an index with a specific type
715
764
  #
716
765
  # add_index(:developers, :name, type: :fulltext)
@@ -757,7 +806,7 @@ module ActiveRecord
757
806
  def rename_index(table_name, old_name, new_name)
758
807
  validate_index_length!(table_name, new_name)
759
808
 
760
- # this is a naive implementation; some DBs may support this more efficiently (Postgres, for instance)
809
+ # this is a naive implementation; some DBs may support this more efficiently (PostgreSQL, for instance)
761
810
  old_index_def = indexes(table_name).detect { |i| i.name == old_name }
762
811
  return unless old_index_def
763
812
  add_index(table_name, old_index_def.columns, name: new_name, unique: old_index_def.unique)
@@ -779,24 +828,19 @@ module ActiveRecord
779
828
  end
780
829
 
781
830
  # Verifies the existence of an index with a given name.
782
- def index_name_exists?(table_name, index_name, default = nil)
783
- unless default.nil?
784
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
785
- Passing default to #index_name_exists? is deprecated without replacement.
786
- MSG
787
- end
831
+ def index_name_exists?(table_name, index_name)
788
832
  index_name = index_name.to_s
789
833
  indexes(table_name).detect { |i| i.name == index_name }
790
834
  end
791
835
 
792
- # Adds a reference. The reference column is an integer by default,
836
+ # Adds a reference. The reference column is a bigint by default,
793
837
  # the <tt>:type</tt> option can be used to specify a different type.
794
838
  # Optionally adds a +_type+ column, if <tt>:polymorphic</tt> option is provided.
795
839
  # #add_reference and #add_belongs_to are acceptable.
796
840
  #
797
841
  # The +options+ hash can include the following keys:
798
842
  # [<tt>:type</tt>]
799
- # The reference column type. Defaults to +:integer+.
843
+ # The reference column type. Defaults to +:bigint+.
800
844
  # [<tt>:index</tt>]
801
845
  # Add an appropriate index. Defaults to true.
802
846
  # See #add_index for usage of this option.
@@ -807,7 +851,7 @@ module ActiveRecord
807
851
  # [<tt>:null</tt>]
808
852
  # Whether the column allows nulls. Defaults to true.
809
853
  #
810
- # ====== Create a user_id integer column
854
+ # ====== Create a user_id bigint column
811
855
  #
812
856
  # add_reference(:products, :user)
813
857
  #
@@ -920,6 +964,8 @@ module ActiveRecord
920
964
  # Action that happens <tt>ON DELETE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
921
965
  # [<tt>:on_update</tt>]
922
966
  # Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
967
+ # [<tt>:validate</tt>]
968
+ # (Postgres only) Specify whether or not the constraint should be validated. Defaults to +true+.
923
969
  def add_foreign_key(from_table, to_table, options = {})
924
970
  return unless supports_foreign_keys?
925
971
 
@@ -974,16 +1020,6 @@ module ActiveRecord
974
1020
  foreign_key_for(from_table, options_or_to_table).present?
975
1021
  end
976
1022
 
977
- def foreign_key_for(from_table, options_or_to_table = {}) # :nodoc:
978
- return unless supports_foreign_keys?
979
- foreign_keys(from_table).detect { |fk| fk.defined_for? options_or_to_table }
980
- end
981
-
982
- def foreign_key_for!(from_table, options_or_to_table = {}) # :nodoc:
983
- foreign_key_for(from_table, options_or_to_table) || \
984
- raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}")
985
- end
986
-
987
1023
  def foreign_key_column_for(table_name) # :nodoc:
988
1024
  prefix = Base.table_name_prefix
989
1025
  suffix = Base.table_name_suffix
@@ -1000,31 +1036,8 @@ module ActiveRecord
1000
1036
 
1001
1037
  def dump_schema_information #:nodoc:
1002
1038
  versions = ActiveRecord::SchemaMigration.all_versions
1003
- insert_versions_sql(versions)
1004
- end
1005
-
1006
- def insert_versions_sql(versions) # :nodoc:
1007
- sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1008
-
1009
- if versions.is_a?(Array)
1010
- sql = "INSERT INTO #{sm_table} (version) VALUES\n"
1011
- sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
1012
- sql << ";\n\n"
1013
- sql
1014
- else
1015
- "INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)});"
1016
- end
1017
- end
1018
-
1019
- def initialize_schema_migrations_table # :nodoc:
1020
- ActiveRecord::SchemaMigration.create_table
1021
- end
1022
- deprecate :initialize_schema_migrations_table
1023
-
1024
- def initialize_internal_metadata_table # :nodoc:
1025
- ActiveRecord::InternalMetadata.create_table
1039
+ insert_versions_sql(versions) if versions.any?
1026
1040
  end
1027
- deprecate :initialize_internal_metadata_table
1028
1041
 
1029
1042
  def internal_string_options_for_primary_key # :nodoc:
1030
1043
  { primary_key: true }
@@ -1036,8 +1049,8 @@ module ActiveRecord
1036
1049
  sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1037
1050
 
1038
1051
  migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
1039
- versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
1040
- ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
1052
+ versions = migration_context.migration_files.map do |file|
1053
+ migration_context.parse_migration_filename(file).first.to_i
1041
1054
  end
1042
1055
 
1043
1056
  unless migrated.include?(version)
@@ -1131,7 +1144,7 @@ module ActiveRecord
1131
1144
  def add_index_options(table_name, column_name, comment: nil, **options) # :nodoc:
1132
1145
  column_names = index_column_names(column_name)
1133
1146
 
1134
- options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type)
1147
+ options.assert_valid_keys(:unique, :order, :name, :where, :length, :internal, :using, :algorithm, :type, :opclass)
1135
1148
 
1136
1149
  index_type = options[:type].to_s if options.key?(:type)
1137
1150
  index_type ||= options[:unique] ? "UNIQUE" : ""
@@ -1170,30 +1183,36 @@ module ActiveRecord
1170
1183
  end
1171
1184
 
1172
1185
  # Changes the comment for a column or removes it if +nil+.
1173
- def change_column_comment(table_name, column_name, comment) #:nodoc:
1186
+ def change_column_comment(table_name, column_name, comment)
1174
1187
  raise NotImplementedError, "#{self.class} does not support changing column comments"
1175
1188
  end
1176
1189
 
1190
+ def create_schema_dumper(options) # :nodoc:
1191
+ SchemaDumper.create(self, options)
1192
+ end
1193
+
1177
1194
  private
1178
1195
  def column_options_keys
1179
1196
  [:limit, :precision, :scale, :default, :null, :collation, :comment]
1180
1197
  end
1181
1198
 
1182
1199
  def add_index_sort_order(quoted_columns, **options)
1183
- if order = options[:order]
1184
- case order
1185
- when Hash
1186
- order = order.symbolize_keys
1187
- quoted_columns.each { |name, column| column << " #{order[name].upcase}" if order[name].present? }
1188
- when String
1189
- quoted_columns.each { |name, column| column << " #{order.upcase}" if order.present? }
1190
- end
1200
+ orders = options_for_index_columns(options[:order])
1201
+ quoted_columns.each do |name, column|
1202
+ column << " #{orders[name].upcase}" if orders[name].present?
1191
1203
  end
1204
+ end
1192
1205
 
1193
- quoted_columns
1206
+ def options_for_index_columns(options)
1207
+ if options.is_a?(Hash)
1208
+ options.symbolize_keys
1209
+ else
1210
+ Hash.new { |hash, column| hash[column] = options }
1211
+ end
1194
1212
  end
1195
1213
 
1196
- # Overridden by the MySQL adapter for supporting index lengths
1214
+ # Overridden by the MySQL adapter for supporting index lengths and by
1215
+ # the PostgreSQL adapter for supporting operator classes.
1197
1216
  def add_options_for_index_columns(quoted_columns, **options)
1198
1217
  if supports_index_sort_order?
1199
1218
  quoted_columns = add_index_sort_order(quoted_columns, options)
@@ -1261,6 +1280,10 @@ module ActiveRecord
1261
1280
  end
1262
1281
  end
1263
1282
 
1283
+ def schema_creation
1284
+ SchemaCreation.new(self)
1285
+ end
1286
+
1264
1287
  def create_table_definition(*args)
1265
1288
  TableDefinition.new(*args)
1266
1289
  end
@@ -1269,6 +1292,17 @@ module ActiveRecord
1269
1292
  AlterTable.new create_table_definition(name)
1270
1293
  end
1271
1294
 
1295
+ def fetch_type_metadata(sql_type)
1296
+ cast_type = lookup_cast_type(sql_type)
1297
+ SqlTypeMetadata.new(
1298
+ sql_type: sql_type,
1299
+ type: cast_type.type,
1300
+ limit: cast_type.limit,
1301
+ precision: cast_type.precision,
1302
+ scale: cast_type.scale,
1303
+ )
1304
+ end
1305
+
1272
1306
  def index_column_names(column_names)
1273
1307
  if column_names.is_a?(String) && /\W/.match?(column_names)
1274
1308
  column_names
@@ -1286,13 +1320,32 @@ module ActiveRecord
1286
1320
  end
1287
1321
 
1288
1322
  def foreign_key_name(table_name, options)
1289
- identifier = "#{table_name}_#{options.fetch(:column)}_fk"
1290
- hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
1291
1323
  options.fetch(:name) do
1324
+ identifier = "#{table_name}_#{options.fetch(:column)}_fk"
1325
+ hashed_identifier = Digest::SHA256.hexdigest(identifier).first(10)
1326
+
1292
1327
  "fk_rails_#{hashed_identifier}"
1293
1328
  end
1294
1329
  end
1295
1330
 
1331
+ def foreign_key_for(from_table, options_or_to_table = {})
1332
+ return unless supports_foreign_keys?
1333
+ foreign_keys(from_table).detect { |fk| fk.defined_for? options_or_to_table }
1334
+ end
1335
+
1336
+ def foreign_key_for!(from_table, options_or_to_table = {})
1337
+ foreign_key_for(from_table, options_or_to_table) || \
1338
+ raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}")
1339
+ end
1340
+
1341
+ def extract_foreign_key_action(specifier)
1342
+ case specifier
1343
+ when "CASCADE"; :cascade
1344
+ when "SET NULL"; :nullify
1345
+ when "RESTRICT"; :restrict
1346
+ end
1347
+ end
1348
+
1296
1349
  def validate_index_length!(table_name, new_name, internal = false)
1297
1350
  max_index_length = internal ? index_name_length : allowed_index_name_length
1298
1351
 
@@ -1313,6 +1366,33 @@ module ActiveRecord
1313
1366
  options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
1314
1367
  end
1315
1368
 
1369
+ def add_column_for_alter(table_name, column_name, type, options = {})
1370
+ td = create_table_definition(table_name)
1371
+ cd = td.new_column_definition(column_name, type, options)
1372
+ schema_creation.accept(AddColumnDefinition.new(cd))
1373
+ end
1374
+
1375
+ def remove_column_for_alter(table_name, column_name, type = nil, options = {})
1376
+ "DROP COLUMN #{quote_column_name(column_name)}"
1377
+ end
1378
+
1379
+ def remove_columns_for_alter(table_name, *column_names)
1380
+ column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
1381
+ end
1382
+
1383
+ def insert_versions_sql(versions)
1384
+ sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1385
+
1386
+ if versions.is_a?(Array)
1387
+ sql = "INSERT INTO #{sm_table} (version) VALUES\n".dup
1388
+ sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
1389
+ sql << ";\n\n"
1390
+ sql
1391
+ else
1392
+ "INSERT INTO #{sm_table} (version) VALUES (#{quote(versions)});"
1393
+ end
1394
+ end
1395
+
1316
1396
  def data_source_sql(name = nil, type: nil)
1317
1397
  raise NotImplementedError
1318
1398
  end