activerecord 5.1.7 → 5.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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +372 -765
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  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 +19 -27
  10. data/lib/active_record/associations/association.rb +16 -27
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +20 -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 +4 -5
  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 +43 -35
  22. data/lib/active_record/associations/collection_proxy.rb +12 -15
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +3 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +7 -18
  26. data/lib/active_record/associations/has_one_association.rb +4 -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 -56
  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 +23 -43
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  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 +25 -10
  37. data/lib/active_record/associations.rb +31 -54
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  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 +25 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  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 +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +6 -5
  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 -10
  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 +11 -7
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +111 -38
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +157 -29
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +7 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +57 -2
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +158 -78
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +81 -96
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +111 -183
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  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 -2
  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 -30
  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 +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  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 +3 -11
  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.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -6
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +246 -110
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +58 -82
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +80 -90
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +39 -60
  129. data/lib/active_record/counter_cache.rb +15 -12
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +17 -13
  133. data/lib/active_record/errors.rb +54 -21
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +4 -2
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +14 -17
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +40 -2
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +16 -21
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +166 -16
  156. data/lib/active_record/query_cache.rb +11 -6
  157. data/lib/active_record/querying.rb +3 -1
  158. data/lib/active_record/railtie.rb +61 -3
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +110 -192
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +30 -8
  167. data/lib/active_record/relation/delegation.rb +15 -27
  168. data/lib/active_record/relation/finder_methods.rb +75 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +51 -20
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +53 -78
  179. data/lib/active_record/relation/query_attribute.rb +26 -2
  180. data/lib/active_record/relation/query_methods.rb +89 -88
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +3 -1
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +95 -208
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +6 -7
  193. data/lib/active_record/scoping/named.rb +21 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +22 -12
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +26 -15
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +5 -12
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +9 -7
  208. data/lib/active_record/translation.rb +2 -0
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +2 -4
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +35 -5
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +24 -36
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -122
  254. data/lib/active_record/attribute_set/builder.rb +0 -126
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -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:
@@ -77,7 +79,7 @@ module ActiveRecord
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 and PostgreSQL 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
@@ -1003,29 +1039,6 @@ module ActiveRecord
1003
1039
  insert_versions_sql(versions) if versions.any?
1004
1040
  end
1005
1041
 
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
1026
- end
1027
- deprecate :initialize_internal_metadata_table
1028
-
1029
1042
  def internal_string_options_for_primary_key # :nodoc:
1030
1043
  { primary_key: true }
1031
1044
  end
@@ -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
@@ -1,10 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module ConnectionAdapters
3
5
  class TransactionState
4
- VALID_STATES = Set.new([:committed, :rolledback, nil])
5
-
6
6
  def initialize(state = nil)
7
7
  @state = state
8
+ @children = []
9
+ end
10
+
11
+ def add_child(state)
12
+ @children << state
8
13
  end
9
14
 
10
15
  def finalized?
@@ -19,15 +24,43 @@ module ActiveRecord
19
24
  @state == :rolledback
20
25
  end
21
26
 
27
+ def fully_completed?
28
+ completed?
29
+ end
30
+
22
31
  def completed?
23
32
  committed? || rolledback?
24
33
  end
25
34
 
26
35
  def set_state(state)
27
- unless VALID_STATES.include?(state)
36
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
37
+ The set_state method is deprecated and will be removed in
38
+ Rails 6.0. Please use rollback! or commit! to set transaction
39
+ state directly.
40
+ MSG
41
+ case state
42
+ when :rolledback
43
+ rollback!
44
+ when :committed
45
+ commit!
46
+ when nil
47
+ nullify!
48
+ else
28
49
  raise ArgumentError, "Invalid transaction state: #{state}"
29
50
  end
30
- @state = state
51
+ end
52
+
53
+ def rollback!
54
+ @children.each { |c| c.rollback! }
55
+ @state = :rolledback
56
+ end
57
+
58
+ def commit!
59
+ @state = :committed
60
+ end
61
+
62
+ def nullify!
63
+ @state = nil
31
64
  end
32
65
  end
33
66
 
@@ -57,7 +90,7 @@ module ActiveRecord
57
90
  end
58
91
 
59
92
  def rollback
60
- @state.set_state(:rolledback)
93
+ @state.rollback!
61
94
  end
62
95
 
63
96
  def rollback_records
@@ -72,7 +105,7 @@ module ActiveRecord
72
105
  end
73
106
 
74
107
  def commit
75
- @state.set_state(:committed)
108
+ @state.commit!
76
109
  end
77
110
 
78
111
  def before_commit_records
@@ -100,8 +133,11 @@ module ActiveRecord
100
133
  end
101
134
 
102
135
  class SavepointTransaction < Transaction
103
- def initialize(connection, savepoint_name, options, *args)
136
+ def initialize(connection, savepoint_name, parent_transaction, options, *args)
104
137
  super(connection, options, *args)
138
+
139
+ parent_transaction.state.add_child(@state)
140
+
105
141
  if options[:isolation]
106
142
  raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction"
107
143
  end
@@ -155,7 +191,7 @@ module ActiveRecord
155
191
  if @stack.empty?
156
192
  RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks)
157
193
  else
158
- SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options,
194
+ SavepointTransaction.new(@connection, "active_record_#{@stack.size}", @stack.last, options,
159
195
  run_commit_callbacks: run_commit_callbacks)
160
196
  end
161
197
 
@@ -204,7 +240,7 @@ module ActiveRecord
204
240
  rollback_transaction if transaction
205
241
  else
206
242
  begin
207
- commit_transaction
243
+ commit_transaction if transaction
208
244
  rescue Exception
209
245
  rollback_transaction(transaction) unless transaction.state.completed?
210
246
  raise