activerecord 5.2.4.4 → 6.0.3.4

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 (292) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +777 -552
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +10 -2
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +4 -3
  9. data/lib/active_record/association_relation.rb +10 -8
  10. data/lib/active_record/associations.rb +21 -16
  11. data/lib/active_record/associations/alias_tracker.rb +0 -1
  12. data/lib/active_record/associations/association.rb +56 -19
  13. data/lib/active_record/associations/association_scope.rb +4 -6
  14. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  16. data/lib/active_record/associations/builder/association.rb +14 -18
  17. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  18. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  20. data/lib/active_record/associations/builder/has_many.rb +2 -0
  21. data/lib/active_record/associations/builder/has_one.rb +35 -1
  22. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  23. data/lib/active_record/associations/collection_association.rb +12 -23
  24. data/lib/active_record/associations/collection_proxy.rb +13 -17
  25. data/lib/active_record/associations/foreign_association.rb +7 -0
  26. data/lib/active_record/associations/has_many_association.rb +2 -11
  27. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  28. data/lib/active_record/associations/has_one_association.rb +28 -30
  29. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  30. data/lib/active_record/associations/join_dependency.rb +37 -28
  31. data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
  32. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  33. data/lib/active_record/associations/preloader.rb +39 -32
  34. data/lib/active_record/associations/preloader/association.rb +38 -36
  35. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  36. data/lib/active_record/associations/singular_association.rb +2 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods.rb +28 -100
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  41. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  42. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  43. data/lib/active_record/attribute_methods/query.rb +2 -3
  44. data/lib/active_record/attribute_methods/read.rb +15 -54
  45. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  47. data/lib/active_record/attribute_methods/write.rb +17 -25
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +3 -5
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +0 -1
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +103 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +100 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +191 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +142 -215
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +132 -16
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +135 -146
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +103 -61
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations.rb +233 -0
  112. data/lib/active_record/database_configurations/database_config.rb +37 -0
  113. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  114. data/lib/active_record/database_configurations/url_config.rb +78 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +37 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +5 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector.rb +74 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  135. data/lib/active_record/migration.rb +104 -85
  136. data/lib/active_record/migration/command_recorder.rb +54 -22
  137. data/lib/active_record/migration/compatibility.rb +79 -52
  138. data/lib/active_record/migration/join_table.rb +0 -1
  139. data/lib/active_record/model_schema.rb +33 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -43
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +40 -38
  151. data/lib/active_record/relation.rb +322 -80
  152. data/lib/active_record/relation/batches.rb +13 -11
  153. data/lib/active_record/relation/calculations.rb +54 -48
  154. data/lib/active_record/relation/delegation.rb +33 -49
  155. data/lib/active_record/relation/finder_methods.rb +23 -28
  156. data/lib/active_record/relation/from_clause.rb +4 -0
  157. data/lib/active_record/relation/merger.rb +11 -21
  158. data/lib/active_record/relation/predicate_builder.rb +5 -11
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  160. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  163. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  164. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  165. data/lib/active_record/relation/query_attribute.rb +13 -8
  166. data/lib/active_record/relation/query_methods.rb +221 -70
  167. data/lib/active_record/relation/spawn_methods.rb +1 -2
  168. data/lib/active_record/relation/where_clause.rb +14 -11
  169. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping.rb +8 -9
  176. data/lib/active_record/scoping/default.rb +4 -6
  177. data/lib/active_record/scoping/named.rb +21 -17
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +225 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type.rb +3 -5
  193. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  194. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  195. data/lib/active_record/type/serialized.rb +0 -1
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type_caster/connection.rb +15 -14
  199. data/lib/active_record/type_caster/map.rb +1 -4
  200. data/lib/active_record/validations.rb +3 -3
  201. data/lib/active_record/validations/associated.rb +1 -2
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/arel.rb +62 -0
  204. data/lib/arel/alias_predication.rb +9 -0
  205. data/lib/arel/attributes.rb +22 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/collectors/bind.rb +24 -0
  208. data/lib/arel/collectors/composite.rb +31 -0
  209. data/lib/arel/collectors/plain_string.rb +20 -0
  210. data/lib/arel/collectors/sql_string.rb +20 -0
  211. data/lib/arel/collectors/substitute_binds.rb +28 -0
  212. data/lib/arel/crud.rb +42 -0
  213. data/lib/arel/delete_manager.rb +18 -0
  214. data/lib/arel/errors.rb +9 -0
  215. data/lib/arel/expressions.rb +29 -0
  216. data/lib/arel/factory_methods.rb +49 -0
  217. data/lib/arel/insert_manager.rb +49 -0
  218. data/lib/arel/math.rb +45 -0
  219. data/lib/arel/nodes.rb +68 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/order_predications.rb +13 -0
  264. data/lib/arel/predications.rb +256 -0
  265. data/lib/arel/select_manager.rb +271 -0
  266. data/lib/arel/table.rb +110 -0
  267. data/lib/arel/tree_manager.rb +72 -0
  268. data/lib/arel/update_manager.rb +34 -0
  269. data/lib/arel/visitors.rb +20 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/window_predications.rb +9 -0
  284. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  285. data/lib/rails/generators/active_record/migration.rb +14 -2
  286. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  287. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  288. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  289. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  290. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  291. metadata +115 -29
  292. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash/compact"
4
-
5
3
  module ActiveRecord
6
4
  module ConnectionAdapters # :nodoc:
7
5
  class SchemaDumper < SchemaDumper # :nodoc:
@@ -17,7 +15,7 @@ module ActiveRecord
17
15
  def column_spec_for_primary_key(column)
18
16
  return {} if default_primary_key?(column)
19
17
  spec = { id: schema_type(column).inspect }
20
- spec.merge!(prepare_column_options(column).except!(:null))
18
+ spec.merge!(prepare_column_options(column).except!(:null, :comment))
21
19
  spec[:default] ||= "nil" if explicit_primary_key_default?(column)
22
20
  spec
23
21
  end
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "active_record/migration/join_table"
4
4
  require "active_support/core_ext/string/access"
5
+ require "active_support/deprecation"
5
6
  require "digest/sha2"
6
7
 
7
8
  module ActiveRecord
@@ -129,11 +130,11 @@ module ActiveRecord
129
130
  # column_exists?(:suppliers, :name, :string, null: false)
130
131
  # column_exists?(:suppliers, :tax, :decimal, precision: 8, scale: 2)
131
132
  #
132
- def column_exists?(table_name, column_name, type = nil, options = {})
133
+ def column_exists?(table_name, column_name, type = nil, **options)
133
134
  column_name = column_name.to_s
134
135
  checks = []
135
136
  checks << lambda { |c| c.name == column_name }
136
- checks << lambda { |c| c.type == type } if type
137
+ checks << lambda { |c| c.type == type.to_sym rescue nil } if type
137
138
  column_options_keys.each do |attr|
138
139
  checks << lambda { |c| c.send(attr) == options[attr] } if options.key?(attr)
139
140
  end
@@ -205,19 +206,22 @@ module ActiveRecord
205
206
  # Set to true to drop the table before creating it.
206
207
  # Set to +:cascade+ to drop dependent objects as well.
207
208
  # Defaults to false.
209
+ # [<tt>:if_not_exists</tt>]
210
+ # Set to true to avoid raising an error when the table already exists.
211
+ # Defaults to false.
208
212
  # [<tt>:as</tt>]
209
213
  # SQL to use to generate the table. When this option is used, the block is
210
214
  # ignored, as are the <tt>:id</tt> and <tt>:primary_key</tt> options.
211
215
  #
212
216
  # ====== Add a backend specific option to the generated SQL (MySQL)
213
217
  #
214
- # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8')
218
+ # create_table(:suppliers, options: 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4')
215
219
  #
216
220
  # generates:
217
221
  #
218
222
  # CREATE TABLE suppliers (
219
223
  # id bigint auto_increment PRIMARY KEY
220
- # ) ENGINE=InnoDB DEFAULT CHARSET=utf8
224
+ # ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
221
225
  #
222
226
  # ====== Rename the primary key column
223
227
  #
@@ -287,8 +291,8 @@ module ActiveRecord
287
291
  # SELECT * FROM orders INNER JOIN line_items ON order_id=orders.id
288
292
  #
289
293
  # See also TableDefinition#column for details on how to create columns.
290
- def create_table(table_name, comment: nil, **options)
291
- td = create_table_definition table_name, options[:temporary], options[:options], options[:as], comment: comment
294
+ def create_table(table_name, **options)
295
+ td = create_table_definition(table_name, **options)
292
296
 
293
297
  if options[:id] != false && !options[:as]
294
298
  pk = options.fetch(:primary_key) do
@@ -298,14 +302,14 @@ module ActiveRecord
298
302
  if pk.is_a?(Array)
299
303
  td.primary_keys pk
300
304
  else
301
- td.primary_key pk, options.fetch(:id, :primary_key), options
305
+ td.primary_key pk, options.fetch(:id, :primary_key), **options.except(:comment)
302
306
  end
303
307
  end
304
308
 
305
309
  yield td if block_given?
306
310
 
307
311
  if options[:force]
308
- drop_table(table_name, options.merge(if_exists: true))
312
+ drop_table(table_name, **options, if_exists: true)
309
313
  end
310
314
 
311
315
  result = execute schema_creation.accept td
@@ -317,7 +321,9 @@ module ActiveRecord
317
321
  end
318
322
 
319
323
  if supports_comments? && !supports_comments_in_create?
320
- change_table_comment(table_name, comment) if comment.present?
324
+ if table_comment = options[:comment].presence
325
+ change_table_comment(table_name, table_comment)
326
+ end
321
327
 
322
328
  td.columns.each do |column|
323
329
  change_column_comment(table_name, column.name, column.comment) if column.comment.present?
@@ -372,9 +378,9 @@ module ActiveRecord
372
378
 
373
379
  t1_ref, t2_ref = [table_1, table_2].map { |t| t.to_s.singularize }
374
380
 
375
- create_table(join_table_name, options.merge!(id: false)) do |td|
376
- td.references t1_ref, column_options
377
- td.references t2_ref, column_options
381
+ create_table(join_table_name, **options.merge!(id: false)) do |td|
382
+ td.references t1_ref, **column_options
383
+ td.references t2_ref, **column_options
378
384
  yield td if block_given?
379
385
  end
380
386
  end
@@ -385,7 +391,7 @@ module ActiveRecord
385
391
  # Although this command ignores the block if one is given, it can be helpful
386
392
  # to provide one in a migration's +change+ method so it can be reverted.
387
393
  # In that case, the block will be used by #create_join_table.
388
- def drop_join_table(table_1, table_2, options = {})
394
+ def drop_join_table(table_1, table_2, **options)
389
395
  join_table_name = find_join_table_name(table_1, table_2, options)
390
396
  drop_table(join_table_name)
391
397
  end
@@ -462,7 +468,7 @@ module ActiveRecord
462
468
  # end
463
469
  #
464
470
  # See also Table for details on all of the various column transformations.
465
- def change_table(table_name, options = {})
471
+ def change_table(table_name, **options)
466
472
  if supports_bulk_alter? && options[:bulk]
467
473
  recorder = ActiveRecord::Migration::CommandRecorder.new(self)
468
474
  yield update_table_definition(table_name, recorder)
@@ -492,7 +498,7 @@ module ActiveRecord
492
498
  # Although this command ignores most +options+ and the block if one is given,
493
499
  # it can be helpful to provide these in a migration's +change+ method so it can be reverted.
494
500
  # In that case, +options+ and the block will be used by #create_table.
495
- def drop_table(table_name, options = {})
501
+ def drop_table(table_name, **options)
496
502
  execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}"
497
503
  end
498
504
 
@@ -512,16 +518,20 @@ module ActiveRecord
512
518
  # Available options are (none of these exists by default):
513
519
  # * <tt>:limit</tt> -
514
520
  # Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column
515
- # and number of bytes for <tt>:text</tt>, <tt>:binary</tt> and <tt>:integer</tt> columns.
521
+ # and number of bytes for <tt>:text</tt>, <tt>:binary</tt>, and <tt>:integer</tt> columns.
516
522
  # This option is ignored by some backends.
517
523
  # * <tt>:default</tt> -
518
524
  # The column's default value. Use +nil+ for +NULL+.
519
525
  # * <tt>:null</tt> -
520
526
  # Allows or disallows +NULL+ values in the column.
521
527
  # * <tt>:precision</tt> -
522
- # Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
528
+ # Specifies the precision for the <tt>:decimal</tt>, <tt>:numeric</tt>,
529
+ # <tt>:datetime</tt>, and <tt>:time</tt> columns.
523
530
  # * <tt>:scale</tt> -
524
531
  # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
532
+ # * <tt>:collation</tt> -
533
+ # Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
534
+ # column will have the same collation as the table.
525
535
  # * <tt>:comment</tt> -
526
536
  # Specifies the comment for the column. This option is ignored by some backends.
527
537
  #
@@ -575,9 +585,9 @@ module ActiveRecord
575
585
  # # Defines a column with a database-specific type.
576
586
  # add_column(:shapes, :triangle, 'polygon')
577
587
  # # ALTER TABLE "shapes" ADD "triangle" polygon
578
- def add_column(table_name, column_name, type, options = {})
588
+ def add_column(table_name, column_name, type, **options)
579
589
  at = create_alter_table table_name
580
- at.add_column(column_name, type, options)
590
+ at.add_column(column_name, type, **options)
581
591
  execute schema_creation.accept at
582
592
  end
583
593
 
@@ -599,8 +609,9 @@ module ActiveRecord
599
609
  # The +type+ and +options+ parameters will be ignored if present. It can be helpful
600
610
  # to provide these in a migration's +change+ method so it can be reverted.
601
611
  # In that case, +type+ and +options+ will be used by #add_column.
602
- def remove_column(table_name, column_name, type = nil, options = {})
603
- execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
612
+ # Indexes on the column are automatically removed.
613
+ def remove_column(table_name, column_name, type = nil, **options)
614
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, **options)}"
604
615
  end
605
616
 
606
617
  # Changes the column's definition according to the new options.
@@ -760,8 +771,19 @@ module ActiveRecord
760
771
  # CREATE FULLTEXT INDEX index_developers_on_name ON developers (name) -- MySQL
761
772
  #
762
773
  # Note: only supported by MySQL.
774
+ #
775
+ # ====== Creating an index with a specific algorithm
776
+ #
777
+ # add_index(:developers, :name, algorithm: :concurrently)
778
+ # # CREATE INDEX CONCURRENTLY developers_on_name on developers (name)
779
+ #
780
+ # Note: only supported by PostgreSQL.
781
+ #
782
+ # Concurrently adding an index is not supported in a transaction.
783
+ #
784
+ # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
763
785
  def add_index(table_name, column_name, options = {})
764
- index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, options)
786
+ index_name, index_type, index_columns, index_options = add_index_options(table_name, column_name, **options)
765
787
  execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{index_columns})#{index_options}"
766
788
  end
767
789
 
@@ -783,6 +805,15 @@ module ActiveRecord
783
805
  #
784
806
  # remove_index :accounts, name: :by_branch_party
785
807
  #
808
+ # Removes the index named +by_branch_party+ in the +accounts+ table +concurrently+.
809
+ #
810
+ # remove_index :accounts, name: :by_branch_party, algorithm: :concurrently
811
+ #
812
+ # Note: only supported by PostgreSQL.
813
+ #
814
+ # Concurrently removing an index is not supported in a transaction.
815
+ #
816
+ # For more information see the {"Transactional Migrations" section}[rdoc-ref:Migration].
786
817
  def remove_index(table_name, options = {})
787
818
  index_name = index_name_for_remove(table_name, options)
788
819
  execute "DROP INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)}"
@@ -842,17 +873,17 @@ module ActiveRecord
842
873
  # [<tt>:null</tt>]
843
874
  # Whether the column allows nulls. Defaults to true.
844
875
  #
845
- # ====== Create a user_id bigint column
876
+ # ====== Create a user_id bigint column without an index
846
877
  #
847
- # add_reference(:products, :user)
878
+ # add_reference(:products, :user, index: false)
848
879
  #
849
880
  # ====== Create a user_id string column
850
881
  #
851
882
  # add_reference(:products, :user, type: :string)
852
883
  #
853
- # ====== Create supplier_id, supplier_type columns and appropriate index
884
+ # ====== Create supplier_id, supplier_type columns
854
885
  #
855
- # add_reference(:products, :supplier, polymorphic: true, index: true)
886
+ # add_reference(:products, :supplier, polymorphic: true)
856
887
  #
857
888
  # ====== Create a supplier_id column with a unique index
858
889
  #
@@ -871,7 +902,7 @@ module ActiveRecord
871
902
  # add_reference(:products, :supplier, foreign_key: {to_table: :firms})
872
903
  #
873
904
  def add_reference(table_name, ref_name, **options)
874
- ReferenceDefinition.new(ref_name, options).add_to(update_table_definition(table_name, self))
905
+ ReferenceDefinition.new(ref_name, **options).add_to(update_table_definition(table_name, self))
875
906
  end
876
907
  alias :add_belongs_to :add_reference
877
908
 
@@ -880,7 +911,7 @@ module ActiveRecord
880
911
  #
881
912
  # ====== Remove the reference
882
913
  #
883
- # remove_reference(:products, :user, index: true)
914
+ # remove_reference(:products, :user, index: false)
884
915
  #
885
916
  # ====== Remove polymorphic reference
886
917
  #
@@ -888,7 +919,7 @@ module ActiveRecord
888
919
  #
889
920
  # ====== Remove the reference with a foreign key
890
921
  #
891
- # remove_reference(:products, :user, index: true, foreign_key: true)
922
+ # remove_reference(:products, :user, foreign_key: true)
892
923
  #
893
924
  def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
894
925
  if foreign_key
@@ -899,7 +930,7 @@ module ActiveRecord
899
930
  foreign_key_options = { to_table: reference_name }
900
931
  end
901
932
  foreign_key_options[:column] ||= "#{ref_name}_id"
902
- remove_foreign_key(table_name, foreign_key_options)
933
+ remove_foreign_key(table_name, **foreign_key_options)
903
934
  end
904
935
 
905
936
  remove_column(table_name, "#{ref_name}_id")
@@ -956,8 +987,8 @@ module ActiveRecord
956
987
  # [<tt>:on_update</tt>]
957
988
  # Action that happens <tt>ON UPDATE</tt>. Valid values are +:nullify+, +:cascade+ and +:restrict+
958
989
  # [<tt>:validate</tt>]
959
- # (Postgres only) Specify whether or not the constraint should be validated. Defaults to +true+.
960
- def add_foreign_key(from_table, to_table, options = {})
990
+ # (PostgreSQL only) Specify whether or not the constraint should be validated. Defaults to +true+.
991
+ def add_foreign_key(from_table, to_table, **options)
961
992
  return unless supports_foreign_keys?
962
993
 
963
994
  options = foreign_key_options(from_table, to_table, options)
@@ -980,15 +1011,22 @@ module ActiveRecord
980
1011
  #
981
1012
  # remove_foreign_key :accounts, column: :owner_id
982
1013
  #
1014
+ # Removes the foreign key on +accounts.owner_id+.
1015
+ #
1016
+ # remove_foreign_key :accounts, to_table: :owners
1017
+ #
983
1018
  # Removes the foreign key named +special_fk_name+ on the +accounts+ table.
984
1019
  #
985
1020
  # remove_foreign_key :accounts, name: :special_fk_name
986
1021
  #
987
- # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
988
- def remove_foreign_key(from_table, options_or_to_table = {})
1022
+ # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
1023
+ # with an addition of
1024
+ # [<tt>:to_table</tt>]
1025
+ # The name of the table that contains the referenced primary key.
1026
+ def remove_foreign_key(from_table, to_table = nil, **options)
989
1027
  return unless supports_foreign_keys?
990
1028
 
991
- fk_name_to_delete = foreign_key_for!(from_table, options_or_to_table).name
1029
+ fk_name_to_delete = foreign_key_for!(from_table, to_table: to_table, **options).name
992
1030
 
993
1031
  at = create_alter_table from_table
994
1032
  at.drop_foreign_key fk_name_to_delete
@@ -1007,14 +1045,12 @@ module ActiveRecord
1007
1045
  # # Checks to see if a foreign key with a custom name exists.
1008
1046
  # foreign_key_exists?(:accounts, name: "special_fk_name")
1009
1047
  #
1010
- def foreign_key_exists?(from_table, options_or_to_table = {})
1011
- foreign_key_for(from_table, options_or_to_table).present?
1048
+ def foreign_key_exists?(from_table, to_table = nil, **options)
1049
+ foreign_key_for(from_table, to_table: to_table, **options).present?
1012
1050
  end
1013
1051
 
1014
1052
  def foreign_key_column_for(table_name) # :nodoc:
1015
- prefix = Base.table_name_prefix
1016
- suffix = Base.table_name_suffix
1017
- name = table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
1053
+ name = strip_table_name_prefix_and_suffix(table_name)
1018
1054
  "#{name.singularize}_id"
1019
1055
  end
1020
1056
 
@@ -1025,8 +1061,8 @@ module ActiveRecord
1025
1061
  options
1026
1062
  end
1027
1063
 
1028
- def dump_schema_information #:nodoc:
1029
- versions = ActiveRecord::SchemaMigration.all_versions
1064
+ def dump_schema_information # :nodoc:
1065
+ versions = schema_migration.all_versions
1030
1066
  insert_versions_sql(versions) if versions.any?
1031
1067
  end
1032
1068
 
@@ -1034,15 +1070,18 @@ module ActiveRecord
1034
1070
  { primary_key: true }
1035
1071
  end
1036
1072
 
1037
- def assume_migrated_upto_version(version, migrations_paths)
1038
- migrations_paths = Array(migrations_paths)
1073
+ def assume_migrated_upto_version(version, migrations_paths = nil)
1074
+ unless migrations_paths.nil?
1075
+ ActiveSupport::Deprecation.warn(<<~MSG.squish)
1076
+ Passing migrations_paths to #assume_migrated_upto_version is deprecated and will be removed in Rails 6.1.
1077
+ MSG
1078
+ end
1079
+
1039
1080
  version = version.to_i
1040
- sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1081
+ sm_table = quote_table_name(schema_migration.table_name)
1041
1082
 
1042
- migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
1043
- versions = migration_context.migration_files.map do |file|
1044
- migration_context.parse_migration_filename(file).first.to_i
1045
- end
1083
+ migrated = migration_context.get_all_versions
1084
+ versions = migration_context.migrations.map(&:version)
1046
1085
 
1047
1086
  unless migrated.include?(version)
1048
1087
  execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
@@ -1053,13 +1092,7 @@ module ActiveRecord
1053
1092
  if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
1054
1093
  raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
1055
1094
  end
1056
- if supports_multi_insert?
1057
- execute insert_versions_sql(inserting)
1058
- else
1059
- inserting.each do |v|
1060
- execute insert_versions_sql(v)
1061
- end
1062
- end
1095
+ execute insert_versions_sql(inserting)
1063
1096
  end
1064
1097
  end
1065
1098
 
@@ -1085,7 +1118,7 @@ module ActiveRecord
1085
1118
  if (0..6) === precision
1086
1119
  column_type_sql << "(#{precision})"
1087
1120
  else
1088
- raise(ActiveRecordError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6")
1121
+ raise ArgumentError, "No #{native[:name]} type has precision of #{precision}. The allowed range of precision is from 0 to 6"
1089
1122
  end
1090
1123
  elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit])
1091
1124
  column_type_sql << "(#{limit})"
@@ -1112,18 +1145,22 @@ module ActiveRecord
1112
1145
  #
1113
1146
  # add_timestamps(:suppliers, null: true)
1114
1147
  #
1115
- def add_timestamps(table_name, options = {})
1148
+ def add_timestamps(table_name, **options)
1116
1149
  options[:null] = false if options[:null].nil?
1117
1150
 
1118
- add_column table_name, :created_at, :datetime, options
1119
- add_column table_name, :updated_at, :datetime, options
1151
+ if !options.key?(:precision) && supports_datetime_with_precision?
1152
+ options[:precision] = 6
1153
+ end
1154
+
1155
+ add_column table_name, :created_at, :datetime, **options
1156
+ add_column table_name, :updated_at, :datetime, **options
1120
1157
  end
1121
1158
 
1122
1159
  # Removes the timestamp columns (+created_at+ and +updated_at+) from the table definition.
1123
1160
  #
1124
1161
  # remove_timestamps(:suppliers)
1125
1162
  #
1126
- def remove_timestamps(table_name, options = {})
1163
+ def remove_timestamps(table_name, **options)
1127
1164
  remove_column table_name, :updated_at
1128
1165
  remove_column table_name, :created_at
1129
1166
  end
@@ -1159,7 +1196,7 @@ module ActiveRecord
1159
1196
  if data_source_exists?(table_name) && index_name_exists?(table_name, index_name)
1160
1197
  raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
1161
1198
  end
1162
- index_columns = quoted_columns_for_index(column_names, options).join(", ")
1199
+ index_columns = quoted_columns_for_index(column_names, **options).join(", ")
1163
1200
 
1164
1201
  [index_name, index_type, index_columns, index_options, algorithm, using, comment]
1165
1202
  end
@@ -1169,12 +1206,22 @@ module ActiveRecord
1169
1206
  end
1170
1207
 
1171
1208
  # Changes the comment for a table or removes it if +nil+.
1172
- def change_table_comment(table_name, comment)
1209
+ #
1210
+ # Passing a hash containing +:from+ and +:to+ will make this change
1211
+ # reversible in migration:
1212
+ #
1213
+ # change_table_comment(:posts, from: "old_comment", to: "new_comment")
1214
+ def change_table_comment(table_name, comment_or_changes)
1173
1215
  raise NotImplementedError, "#{self.class} does not support changing table comments"
1174
1216
  end
1175
1217
 
1176
1218
  # Changes the comment for a column or removes it if +nil+.
1177
- def change_column_comment(table_name, column_name, comment)
1219
+ #
1220
+ # Passing a hash containing +:from+ and +:to+ will make this change
1221
+ # reversible in migration:
1222
+ #
1223
+ # change_column_comment(:posts, :state, from: "old_comment", to: "new_comment")
1224
+ def change_column_comment(table_name, column_name, comment_or_changes)
1178
1225
  raise NotImplementedError, "#{self.class} does not support changing column comments"
1179
1226
  end
1180
1227
 
@@ -1206,7 +1253,7 @@ module ActiveRecord
1206
1253
  # the PostgreSQL adapter for supporting operator classes.
1207
1254
  def add_options_for_index_columns(quoted_columns, **options)
1208
1255
  if supports_index_sort_order?
1209
- quoted_columns = add_index_sort_order(quoted_columns, options)
1256
+ quoted_columns = add_index_sort_order(quoted_columns, **options)
1210
1257
  end
1211
1258
 
1212
1259
  quoted_columns
@@ -1216,7 +1263,7 @@ module ActiveRecord
1216
1263
  return [column_names] if column_names.is_a?(String)
1217
1264
 
1218
1265
  quoted_columns = Hash[column_names.map { |name| [name.to_sym, quote_column_name(name).dup] }]
1219
- add_options_for_index_columns(quoted_columns, options).values
1266
+ add_options_for_index_columns(quoted_columns, **options).values
1220
1267
  end
1221
1268
 
1222
1269
  def index_name_for_remove(table_name, options = {})
@@ -1275,8 +1322,8 @@ module ActiveRecord
1275
1322
  SchemaCreation.new(self)
1276
1323
  end
1277
1324
 
1278
- def create_table_definition(*args)
1279
- TableDefinition.new(*args)
1325
+ def create_table_definition(*args, **options)
1326
+ TableDefinition.new(self, *args, **options)
1280
1327
  end
1281
1328
 
1282
1329
  def create_alter_table(name)
@@ -1310,6 +1357,12 @@ module ActiveRecord
1310
1357
  { column: column_names }
1311
1358
  end
1312
1359
 
1360
+ def strip_table_name_prefix_and_suffix(table_name)
1361
+ prefix = Base.table_name_prefix
1362
+ suffix = Base.table_name_suffix
1363
+ table_name.to_s =~ /#{prefix}(.+)#{suffix}/ ? $1 : table_name.to_s
1364
+ end
1365
+
1313
1366
  def foreign_key_name(table_name, options)
1314
1367
  options.fetch(:name) do
1315
1368
  identifier = "#{table_name}_#{options.fetch(:column)}_fk"
@@ -1319,14 +1372,14 @@ module ActiveRecord
1319
1372
  end
1320
1373
  end
1321
1374
 
1322
- def foreign_key_for(from_table, options_or_to_table = {})
1375
+ def foreign_key_for(from_table, **options)
1323
1376
  return unless supports_foreign_keys?
1324
- foreign_keys(from_table).detect { |fk| fk.defined_for? options_or_to_table }
1377
+ foreign_keys(from_table).detect { |fk| fk.defined_for?(**options) }
1325
1378
  end
1326
1379
 
1327
- def foreign_key_for!(from_table, options_or_to_table = {})
1328
- foreign_key_for(from_table, options_or_to_table) || \
1329
- raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{options_or_to_table}")
1380
+ def foreign_key_for!(from_table, to_table: nil, **options)
1381
+ foreign_key_for(from_table, to_table: to_table, **options) ||
1382
+ raise(ArgumentError, "Table '#{from_table}' has no foreign key for #{to_table || options}")
1330
1383
  end
1331
1384
 
1332
1385
  def extract_foreign_key_action(specifier)
@@ -1352,30 +1405,73 @@ module ActiveRecord
1352
1405
  default_or_changes
1353
1406
  end
1354
1407
  end
1408
+ alias :extract_new_comment_value :extract_new_default_value
1355
1409
 
1356
1410
  def can_remove_index_by_name?(options)
1357
1411
  options.is_a?(Hash) && options.key?(:name) && options.except(:name, :algorithm).empty?
1358
1412
  end
1359
1413
 
1360
- def add_column_for_alter(table_name, column_name, type, options = {})
1414
+ def bulk_change_table(table_name, operations)
1415
+ sql_fragments = []
1416
+ non_combinable_operations = []
1417
+
1418
+ operations.each do |command, args|
1419
+ table, arguments = args.shift, args
1420
+ method = :"#{command}_for_alter"
1421
+
1422
+ if respond_to?(method, true)
1423
+ sqls, procs = Array(send(method, table, *arguments)).partition { |v| v.is_a?(String) }
1424
+ sql_fragments << sqls
1425
+ non_combinable_operations.concat(procs)
1426
+ else
1427
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
1428
+ non_combinable_operations.each(&:call)
1429
+ sql_fragments = []
1430
+ non_combinable_operations = []
1431
+ send(command, table, *arguments)
1432
+ end
1433
+ end
1434
+
1435
+ execute "ALTER TABLE #{quote_table_name(table_name)} #{sql_fragments.join(", ")}" unless sql_fragments.empty?
1436
+ non_combinable_operations.each(&:call)
1437
+ end
1438
+
1439
+ def add_column_for_alter(table_name, column_name, type, **options)
1361
1440
  td = create_table_definition(table_name)
1362
- cd = td.new_column_definition(column_name, type, options)
1441
+ cd = td.new_column_definition(column_name, type, **options)
1363
1442
  schema_creation.accept(AddColumnDefinition.new(cd))
1364
1443
  end
1365
1444
 
1366
- def remove_column_for_alter(table_name, column_name, type = nil, options = {})
1445
+ def remove_column_for_alter(table_name, column_name, type = nil, **options)
1367
1446
  "DROP COLUMN #{quote_column_name(column_name)}"
1368
1447
  end
1369
1448
 
1370
- def remove_columns_for_alter(table_name, *column_names)
1449
+ def remove_columns_for_alter(table_name, *column_names, **options)
1371
1450
  column_names.map { |column_name| remove_column_for_alter(table_name, column_name) }
1372
1451
  end
1373
1452
 
1453
+ def add_timestamps_for_alter(table_name, **options)
1454
+ options[:null] = false if options[:null].nil?
1455
+
1456
+ if !options.key?(:precision) && supports_datetime_with_precision?
1457
+ options[:precision] = 6
1458
+ end
1459
+
1460
+ [
1461
+ add_column_for_alter(table_name, :created_at, :datetime, **options),
1462
+ add_column_for_alter(table_name, :updated_at, :datetime, **options)
1463
+ ]
1464
+ end
1465
+
1466
+ def remove_timestamps_for_alter(table_name, **options)
1467
+ remove_columns_for_alter(table_name, :updated_at, :created_at)
1468
+ end
1469
+
1374
1470
  def insert_versions_sql(versions)
1375
- sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1471
+ sm_table = quote_table_name(schema_migration.table_name)
1376
1472
 
1377
1473
  if versions.is_a?(Array)
1378
- sql = "INSERT INTO #{sm_table} (version) VALUES\n".dup
1474
+ sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
1379
1475
  sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
1380
1476
  sql << ";\n\n"
1381
1477
  sql