activerecord 5.2.4.5 → 6.0.0.beta1

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 (241) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -739
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +2 -1
  7. data/lib/active_record/aggregations.rb +4 -2
  8. data/lib/active_record/associations.rb +16 -12
  9. data/lib/active_record/associations/association.rb +35 -19
  10. data/lib/active_record/associations/association_scope.rb +4 -6
  11. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +14 -50
  14. data/lib/active_record/associations/builder/collection_association.rb +3 -3
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
  16. data/lib/active_record/associations/collection_association.rb +11 -25
  17. data/lib/active_record/associations/collection_proxy.rb +32 -6
  18. data/lib/active_record/associations/foreign_association.rb +7 -0
  19. data/lib/active_record/associations/has_many_association.rb +1 -1
  20. data/lib/active_record/associations/has_many_through_association.rb +25 -18
  21. data/lib/active_record/associations/has_one_association.rb +28 -30
  22. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  23. data/lib/active_record/associations/join_dependency.rb +15 -20
  24. data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
  25. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  26. data/lib/active_record/associations/preloader.rb +32 -29
  27. data/lib/active_record/associations/preloader/association.rb +1 -2
  28. data/lib/active_record/associations/singular_association.rb +2 -16
  29. data/lib/active_record/attribute_assignment.rb +7 -10
  30. data/lib/active_record/attribute_methods.rb +34 -56
  31. data/lib/active_record/attribute_methods/dirty.rb +64 -26
  32. data/lib/active_record/attribute_methods/primary_key.rb +8 -7
  33. data/lib/active_record/attribute_methods/read.rb +16 -48
  34. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  35. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  36. data/lib/active_record/attribute_methods/write.rb +15 -16
  37. data/lib/active_record/autosave_association.rb +7 -21
  38. data/lib/active_record/base.rb +2 -2
  39. data/lib/active_record/callbacks.rb +3 -17
  40. data/lib/active_record/collection_cache_key.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
  42. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
  53. data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
  54. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
  55. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
  56. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  57. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
  58. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
  59. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
  60. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
  61. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  63. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  64. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
  65. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
  66. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  67. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
  68. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  69. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  70. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
  71. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
  72. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
  73. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
  75. data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
  76. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
  77. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
  78. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
  79. data/lib/active_record/connection_handling.rb +132 -26
  80. data/lib/active_record/core.rb +76 -43
  81. data/lib/active_record/counter_cache.rb +4 -29
  82. data/lib/active_record/database_configurations.rb +184 -0
  83. data/lib/active_record/database_configurations/database_config.rb +37 -0
  84. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  85. data/lib/active_record/database_configurations/url_config.rb +74 -0
  86. data/lib/active_record/enum.rb +22 -7
  87. data/lib/active_record/errors.rb +24 -21
  88. data/lib/active_record/explain.rb +1 -1
  89. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  90. data/lib/active_record/fixture_set/render_context.rb +17 -0
  91. data/lib/active_record/fixture_set/table_row.rb +153 -0
  92. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  93. data/lib/active_record/fixtures.rb +140 -472
  94. data/lib/active_record/gem_version.rb +4 -4
  95. data/lib/active_record/inheritance.rb +12 -2
  96. data/lib/active_record/integration.rb +56 -16
  97. data/lib/active_record/internal_metadata.rb +5 -1
  98. data/lib/active_record/locking/optimistic.rb +2 -2
  99. data/lib/active_record/locking/pessimistic.rb +3 -3
  100. data/lib/active_record/log_subscriber.rb +7 -26
  101. data/lib/active_record/migration.rb +38 -37
  102. data/lib/active_record/migration/command_recorder.rb +35 -5
  103. data/lib/active_record/migration/compatibility.rb +34 -16
  104. data/lib/active_record/model_schema.rb +30 -9
  105. data/lib/active_record/nested_attributes.rb +2 -2
  106. data/lib/active_record/no_touching.rb +7 -0
  107. data/lib/active_record/persistence.rb +18 -7
  108. data/lib/active_record/query_cache.rb +11 -4
  109. data/lib/active_record/querying.rb +19 -11
  110. data/lib/active_record/railtie.rb +71 -42
  111. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  112. data/lib/active_record/railties/controller_runtime.rb +30 -35
  113. data/lib/active_record/railties/databases.rake +94 -43
  114. data/lib/active_record/reflection.rb +60 -44
  115. data/lib/active_record/relation.rb +150 -69
  116. data/lib/active_record/relation/batches.rb +13 -10
  117. data/lib/active_record/relation/calculations.rb +38 -28
  118. data/lib/active_record/relation/delegation.rb +4 -13
  119. data/lib/active_record/relation/finder_methods.rb +12 -25
  120. data/lib/active_record/relation/merger.rb +2 -6
  121. data/lib/active_record/relation/predicate_builder.rb +4 -6
  122. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  123. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  124. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  125. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  126. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  127. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  128. data/lib/active_record/relation/query_attribute.rb +15 -12
  129. data/lib/active_record/relation/query_methods.rb +29 -52
  130. data/lib/active_record/relation/where_clause.rb +4 -0
  131. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  132. data/lib/active_record/result.rb +30 -11
  133. data/lib/active_record/sanitization.rb +2 -39
  134. data/lib/active_record/schema.rb +1 -10
  135. data/lib/active_record/schema_dumper.rb +12 -6
  136. data/lib/active_record/schema_migration.rb +4 -0
  137. data/lib/active_record/scoping.rb +9 -8
  138. data/lib/active_record/scoping/default.rb +10 -3
  139. data/lib/active_record/scoping/named.rb +10 -14
  140. data/lib/active_record/statement_cache.rb +32 -5
  141. data/lib/active_record/store.rb +39 -8
  142. data/lib/active_record/table_metadata.rb +1 -4
  143. data/lib/active_record/tasks/database_tasks.rb +89 -23
  144. data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
  145. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
  146. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
  147. data/lib/active_record/test_databases.rb +38 -0
  148. data/lib/active_record/test_fixtures.rb +224 -0
  149. data/lib/active_record/timestamp.rb +4 -6
  150. data/lib/active_record/transactions.rb +3 -22
  151. data/lib/active_record/translation.rb +1 -1
  152. data/lib/active_record/type.rb +3 -4
  153. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  154. data/lib/active_record/type_caster/connection.rb +1 -6
  155. data/lib/active_record/type_caster/map.rb +1 -4
  156. data/lib/active_record/validations/uniqueness.rb +13 -25
  157. data/lib/arel.rb +44 -0
  158. data/lib/arel/alias_predication.rb +9 -0
  159. data/lib/arel/attributes.rb +22 -0
  160. data/lib/arel/attributes/attribute.rb +37 -0
  161. data/lib/arel/collectors/bind.rb +24 -0
  162. data/lib/arel/collectors/composite.rb +31 -0
  163. data/lib/arel/collectors/plain_string.rb +20 -0
  164. data/lib/arel/collectors/sql_string.rb +20 -0
  165. data/lib/arel/collectors/substitute_binds.rb +28 -0
  166. data/lib/arel/crud.rb +42 -0
  167. data/lib/arel/delete_manager.rb +18 -0
  168. data/lib/arel/errors.rb +9 -0
  169. data/lib/arel/expressions.rb +29 -0
  170. data/lib/arel/factory_methods.rb +49 -0
  171. data/lib/arel/insert_manager.rb +49 -0
  172. data/lib/arel/math.rb +45 -0
  173. data/lib/arel/nodes.rb +67 -0
  174. data/lib/arel/nodes/and.rb +32 -0
  175. data/lib/arel/nodes/ascending.rb +23 -0
  176. data/lib/arel/nodes/binary.rb +52 -0
  177. data/lib/arel/nodes/bind_param.rb +36 -0
  178. data/lib/arel/nodes/case.rb +55 -0
  179. data/lib/arel/nodes/casted.rb +50 -0
  180. data/lib/arel/nodes/count.rb +12 -0
  181. data/lib/arel/nodes/delete_statement.rb +45 -0
  182. data/lib/arel/nodes/descending.rb +23 -0
  183. data/lib/arel/nodes/equality.rb +18 -0
  184. data/lib/arel/nodes/extract.rb +24 -0
  185. data/lib/arel/nodes/false.rb +16 -0
  186. data/lib/arel/nodes/full_outer_join.rb +8 -0
  187. data/lib/arel/nodes/function.rb +44 -0
  188. data/lib/arel/nodes/grouping.rb +8 -0
  189. data/lib/arel/nodes/in.rb +8 -0
  190. data/lib/arel/nodes/infix_operation.rb +80 -0
  191. data/lib/arel/nodes/inner_join.rb +8 -0
  192. data/lib/arel/nodes/insert_statement.rb +37 -0
  193. data/lib/arel/nodes/join_source.rb +20 -0
  194. data/lib/arel/nodes/matches.rb +18 -0
  195. data/lib/arel/nodes/named_function.rb +23 -0
  196. data/lib/arel/nodes/node.rb +50 -0
  197. data/lib/arel/nodes/node_expression.rb +13 -0
  198. data/lib/arel/nodes/outer_join.rb +8 -0
  199. data/lib/arel/nodes/over.rb +15 -0
  200. data/lib/arel/nodes/regexp.rb +16 -0
  201. data/lib/arel/nodes/right_outer_join.rb +8 -0
  202. data/lib/arel/nodes/select_core.rb +63 -0
  203. data/lib/arel/nodes/select_statement.rb +41 -0
  204. data/lib/arel/nodes/sql_literal.rb +16 -0
  205. data/lib/arel/nodes/string_join.rb +11 -0
  206. data/lib/arel/nodes/table_alias.rb +27 -0
  207. data/lib/arel/nodes/terminal.rb +16 -0
  208. data/lib/arel/nodes/true.rb +16 -0
  209. data/lib/arel/nodes/unary.rb +44 -0
  210. data/lib/arel/nodes/unary_operation.rb +20 -0
  211. data/lib/arel/nodes/unqualified_column.rb +22 -0
  212. data/lib/arel/nodes/update_statement.rb +41 -0
  213. data/lib/arel/nodes/values.rb +16 -0
  214. data/lib/arel/nodes/values_list.rb +24 -0
  215. data/lib/arel/nodes/window.rb +126 -0
  216. data/lib/arel/nodes/with.rb +11 -0
  217. data/lib/arel/order_predications.rb +13 -0
  218. data/lib/arel/predications.rb +257 -0
  219. data/lib/arel/select_manager.rb +271 -0
  220. data/lib/arel/table.rb +110 -0
  221. data/lib/arel/tree_manager.rb +72 -0
  222. data/lib/arel/update_manager.rb +34 -0
  223. data/lib/arel/visitors.rb +20 -0
  224. data/lib/arel/visitors/depth_first.rb +199 -0
  225. data/lib/arel/visitors/dot.rb +292 -0
  226. data/lib/arel/visitors/ibm_db.rb +21 -0
  227. data/lib/arel/visitors/informix.rb +56 -0
  228. data/lib/arel/visitors/mssql.rb +143 -0
  229. data/lib/arel/visitors/mysql.rb +83 -0
  230. data/lib/arel/visitors/oracle.rb +159 -0
  231. data/lib/arel/visitors/oracle12.rb +67 -0
  232. data/lib/arel/visitors/postgresql.rb +116 -0
  233. data/lib/arel/visitors/sqlite.rb +39 -0
  234. data/lib/arel/visitors/to_sql.rb +913 -0
  235. data/lib/arel/visitors/visitor.rb +42 -0
  236. data/lib/arel/visitors/where_sql.rb +23 -0
  237. data/lib/arel/window_predications.rb +9 -0
  238. data/lib/rails/generators/active_record/migration.rb +14 -1
  239. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  240. data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
  241. metadata +104 -26
@@ -32,17 +32,17 @@ module ActiveRecord
32
32
  end
33
33
 
34
34
  def enable_query_cache!
35
- @query_cache_enabled[connection_cache_key(current_thread)] = true
35
+ @query_cache_enabled[connection_cache_key(Thread.current)] = true
36
36
  connection.enable_query_cache! if active_connection?
37
37
  end
38
38
 
39
39
  def disable_query_cache!
40
- @query_cache_enabled.delete connection_cache_key(current_thread)
40
+ @query_cache_enabled.delete connection_cache_key(Thread.current)
41
41
  connection.disable_query_cache! if active_connection?
42
42
  end
43
43
 
44
44
  def query_cache_enabled
45
- @query_cache_enabled[connection_cache_key(current_thread)]
45
+ @query_cache_enabled[connection_cache_key(Thread.current)]
46
46
  end
47
47
  end
48
48
 
@@ -96,11 +96,6 @@ module ActiveRecord
96
96
  if @query_cache_enabled && !locked?(arel)
97
97
  arel = arel_from_relation(arel)
98
98
  sql, binds = to_sql_and_binds(arel, binds)
99
-
100
- if preparable.nil?
101
- preparable = prepared_statements ? visitor.preparable : false
102
- end
103
-
104
99
  cache_sql(sql, name, binds) { super(sql, name, binds, preparable: preparable) }
105
100
  else
106
101
  super
@@ -115,12 +110,7 @@ module ActiveRecord
115
110
  if @query_cache[sql].key?(binds)
116
111
  ActiveSupport::Notifications.instrument(
117
112
  "sql.active_record",
118
- sql: sql,
119
- binds: binds,
120
- type_casted_binds: -> { type_casted_binds(binds) },
121
- name: name,
122
- connection_id: object_id,
123
- cached: true,
113
+ cache_notification_info(sql, name, binds)
124
114
  )
125
115
  @query_cache[sql][binds]
126
116
  else
@@ -130,6 +120,19 @@ module ActiveRecord
130
120
  end
131
121
  end
132
122
 
123
+ # Database adapters can override this method to
124
+ # provide custom cache information.
125
+ def cache_notification_info(sql, name, binds)
126
+ {
127
+ sql: sql,
128
+ binds: binds,
129
+ type_casted_binds: -> { type_casted_binds(binds) },
130
+ name: name,
131
+ connection_id: object_id,
132
+ cached: true
133
+ }
134
+ end
135
+
133
136
  # If arel is locked this is a SELECT ... FOR UPDATE or somesuch. Such
134
137
  # queries should not be cached.
135
138
  def locked?(arel)
@@ -60,7 +60,7 @@ module ActiveRecord
60
60
  # Quotes a string, escaping any ' (single quote) and \ (backslash)
61
61
  # characters.
62
62
  def quote_string(s)
63
- s.gsub('\\'.freeze, '\&\&'.freeze).gsub("'".freeze, "''".freeze) # ' (for ruby-mode)
63
+ s.gsub('\\', '\&\&').gsub("'", "''") # ' (for ruby-mode)
64
64
  end
65
65
 
66
66
  # Quotes the column name. Defaults to no quoting.
@@ -95,7 +95,7 @@ module ActiveRecord
95
95
  end
96
96
 
97
97
  def quoted_true
98
- "TRUE".freeze
98
+ "TRUE"
99
99
  end
100
100
 
101
101
  def unquoted_true
@@ -103,7 +103,7 @@ module ActiveRecord
103
103
  end
104
104
 
105
105
  def quoted_false
106
- "FALSE".freeze
106
+ "FALSE"
107
107
  end
108
108
 
109
109
  def unquoted_false
@@ -157,13 +157,9 @@ module ActiveRecord
157
157
  end
158
158
  end
159
159
 
160
- def types_which_need_no_typecasting
161
- [nil, Numeric, String]
162
- end
163
-
164
160
  def _quote(value)
165
161
  case value
166
- when String, ActiveSupport::Multibyte::Chars
162
+ when String, Symbol, ActiveSupport::Multibyte::Chars
167
163
  "'#{quote_string(value.to_s)}'"
168
164
  when true then quoted_true
169
165
  when false then quoted_false
@@ -174,7 +170,6 @@ module ActiveRecord
174
170
  when Type::Binary::Data then quoted_binary(value)
175
171
  when Type::Time::Value then "'#{quoted_time(value)}'"
176
172
  when Date, Time then "'#{quoted_date(value)}'"
177
- when Symbol then "'#{quote_string(value.to_s)}'"
178
173
  when Class then "'#{value}'"
179
174
  else raise TypeError, "can't quote #{value.class.name}"
180
175
  end
@@ -188,10 +183,9 @@ module ActiveRecord
188
183
  when false then unquoted_false
189
184
  # BigDecimals need to be put in a non-normalized form and quoted.
190
185
  when BigDecimal then value.to_s("F")
186
+ when nil, Numeric, String then value
191
187
  when Type::Time::Value then quoted_time(value)
192
188
  when Date, Time then quoted_date(value)
193
- when *types_which_need_no_typecasting
194
- value
195
189
  else raise TypeError
196
190
  end
197
191
  end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/string/strip"
4
-
5
3
  module ActiveRecord
6
4
  module ConnectionAdapters
7
5
  class AbstractAdapter
@@ -17,14 +15,13 @@ module ActiveRecord
17
15
  end
18
16
 
19
17
  delegate :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
20
- :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options, to: :@conn
21
- private :quote_column_name, :quote_table_name, :quote_default_expression, :type_to_sql,
22
- :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options
18
+ :options_include_default?, :supports_indexes_in_create?, :supports_foreign_keys_in_create?, :foreign_key_options,
19
+ to: :@conn, private: true
23
20
 
24
21
  private
25
22
 
26
23
  def visit_AlterTable(o)
27
- sql = "ALTER TABLE #{quote_table_name(o.name)} ".dup
24
+ sql = +"ALTER TABLE #{quote_table_name(o.name)} "
28
25
  sql << o.adds.map { |col| accept col }.join(" ")
29
26
  sql << o.foreign_key_adds.map { |fk| visit_AddForeignKey fk }.join(" ")
30
27
  sql << o.foreign_key_drops.map { |fk| visit_DropForeignKey fk }.join(" ")
@@ -32,17 +29,19 @@ module ActiveRecord
32
29
 
33
30
  def visit_ColumnDefinition(o)
34
31
  o.sql_type = type_to_sql(o.type, o.options)
35
- column_sql = "#{quote_column_name(o.name)} #{o.sql_type}".dup
32
+ column_sql = +"#{quote_column_name(o.name)} #{o.sql_type}"
36
33
  add_column_options!(column_sql, column_options(o)) unless o.type == :primary_key
37
34
  column_sql
38
35
  end
39
36
 
40
37
  def visit_AddColumnDefinition(o)
41
- "ADD #{accept(o.column)}".dup
38
+ +"ADD #{accept(o.column)}"
42
39
  end
43
40
 
44
41
  def visit_TableDefinition(o)
45
- create_sql = "CREATE#{' TEMPORARY' if o.temporary} TABLE #{quote_table_name(o.name)} ".dup
42
+ create_sql = +"CREATE#{table_modifier_in_create(o)} TABLE "
43
+ create_sql << "IF NOT EXISTS " if o.if_not_exists
44
+ create_sql << "#{quote_table_name(o.name)} "
46
45
 
47
46
  statements = o.columns.map { |c| accept c }
48
47
  statements << accept(o.primary_keys) if o.primary_keys
@@ -66,7 +65,7 @@ module ActiveRecord
66
65
  end
67
66
 
68
67
  def visit_ForeignKeyDefinition(o)
69
- sql = <<-SQL.strip_heredoc
68
+ sql = +<<~SQL
70
69
  CONSTRAINT #{quote_column_name(o.name)}
71
70
  FOREIGN KEY (#{quote_column_name(o.column)})
72
71
  REFERENCES #{quote_table_name(o.to_table)} (#{quote_column_name(o.primary_key)})
@@ -122,6 +121,11 @@ module ActiveRecord
122
121
  sql
123
122
  end
124
123
 
124
+ # Returns any SQL string to go between CREATE and TABLE. May be nil.
125
+ def table_modifier_in_create(o)
126
+ " TEMPORARY" if o.temporary
127
+ end
128
+
125
129
  def foreign_key_in_create(from_table, to_table, options)
126
130
  options = foreign_key_options(from_table, to_table, options)
127
131
  accept ForeignKeyDefinition.new(from_table, to_table, options)
@@ -133,7 +137,7 @@ module ActiveRecord
133
137
  when :cascade then "ON #{action} CASCADE"
134
138
  when :restrict then "ON #{action} RESTRICT"
135
139
  else
136
- raise ArgumentError, <<-MSG.strip_heredoc
140
+ raise ArgumentError, <<~MSG
137
141
  '#{dependency}' is not supported for :on_update or :on_delete.
138
142
  Supported values are: :nullify, :cascade, :restrict
139
143
  MSG
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/deprecation"
4
+
3
5
  module ActiveRecord
4
6
  module ConnectionAdapters #:nodoc:
5
7
  # Abstract representation of an index definition on a table. Instances of
@@ -101,6 +103,10 @@ module ActiveRecord
101
103
  end
102
104
  alias validated? validate?
103
105
 
106
+ def export_name_on_schema_dump?
107
+ name !~ ActiveRecord::SchemaDumper.fk_ignore_pattern
108
+ end
109
+
104
110
  def defined_for?(to_table_ord = nil, to_table: nil, **options)
105
111
  if to_table_ord
106
112
  self.to_table == to_table_ord.to_s
@@ -151,13 +157,8 @@ module ActiveRecord
151
157
  end
152
158
  end
153
159
 
154
- # TODO Change this to private once we've dropped Ruby 2.2 support.
155
- # Workaround for Ruby 2.2 "private attribute?" warning.
156
- protected
157
-
158
- attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
159
-
160
160
  private
161
+ attr_reader :name, :polymorphic, :index, :foreign_key, :type, :options
161
162
 
162
163
  def as_options(value)
163
164
  value.is_a?(Hash) ? value : {}
@@ -257,15 +258,25 @@ module ActiveRecord
257
258
  class TableDefinition
258
259
  include ColumnMethods
259
260
 
260
- attr_accessor :indexes
261
- attr_reader :name, :temporary, :options, :as, :foreign_keys, :comment
261
+ attr_reader :name, :temporary, :if_not_exists, :options, :as, :comment, :indexes, :foreign_keys
262
+ attr_writer :indexes
263
+ deprecate :indexes=
262
264
 
263
- def initialize(name, temporary = false, options = nil, as = nil, comment: nil)
265
+ def initialize(
266
+ name,
267
+ temporary: false,
268
+ if_not_exists: false,
269
+ options: nil,
270
+ as: nil,
271
+ comment: nil,
272
+ **
273
+ )
264
274
  @columns_hash = {}
265
275
  @indexes = []
266
276
  @foreign_keys = []
267
277
  @primary_keys = nil
268
278
  @temporary = temporary
279
+ @if_not_exists = if_not_exists
269
280
  @options = options
270
281
  @as = as
271
282
  @name = name
@@ -349,16 +360,20 @@ module ActiveRecord
349
360
  #
350
361
  # create_table :taggings do |t|
351
362
  # t.references :tag, index: { name: 'index_taggings_on_tag_id' }
352
- # t.references :tagger, polymorphic: true, index: true
353
- # t.references :taggable, polymorphic: { default: 'Photo' }
363
+ # t.references :tagger, polymorphic: true
364
+ # t.references :taggable, polymorphic: { default: 'Photo' }, index: false
354
365
  # end
355
366
  def column(name, type, options = {})
356
367
  name = name.to_s
357
368
  type = type.to_sym if type
358
369
  options = options.dup
359
370
 
360
- if @columns_hash[name] && @columns_hash[name].primary_key?
361
- raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
371
+ if @columns_hash[name]
372
+ if @columns_hash[name].primary_key?
373
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
374
+ else
375
+ raise ArgumentError, "you can't define an already defined column '#{name}'."
376
+ end
362
377
  end
363
378
 
364
379
  index_options = options.delete(:index)
@@ -524,7 +539,9 @@ module ActiveRecord
524
539
  #
525
540
  # See TableDefinition#column for details of the options you can use.
526
541
  def column(column_name, type, options = {})
542
+ index_options = options.delete(:index)
527
543
  @base.add_column(name, column_name, type, options)
544
+ index(column_name, index_options.is_a?(Hash) ? index_options : {}) if index_options
528
545
  end
529
546
 
530
547
  # Checks to see if a column exists.
@@ -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:
@@ -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
@@ -100,7 +101,7 @@ module ActiveRecord
100
101
  def index_exists?(table_name, column_name, options = {})
101
102
  column_names = Array(column_name).map(&:to_s)
102
103
  checks = []
103
- checks << lambda { |i| Array(i.columns) == column_names }
104
+ checks << lambda { |i| i.columns == column_names }
104
105
  checks << lambda { |i| i.unique } if options[:unique]
105
106
  checks << lambda { |i| i.name == options[:name].to_s } if options[:name]
106
107
 
@@ -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
@@ -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?
@@ -522,6 +528,9 @@ module ActiveRecord
522
528
  # Specifies the precision for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
523
529
  # * <tt>:scale</tt> -
524
530
  # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns.
531
+ # * <tt>:collation</tt> -
532
+ # Specifies the collation for a <tt>:string</tt> or <tt>:text</tt> column. If not specified, the
533
+ # column will have the same collation as the table.
525
534
  # * <tt>:comment</tt> -
526
535
  # Specifies the comment for the column. This option is ignored by some backends.
527
536
  #
@@ -599,6 +608,7 @@ module ActiveRecord
599
608
  # The +type+ and +options+ parameters will be ignored if present. It can be helpful
600
609
  # to provide these in a migration's +change+ method so it can be reverted.
601
610
  # In that case, +type+ and +options+ will be used by #add_column.
611
+ # Indexes on the column are automatically removed.
602
612
  def remove_column(table_name, column_name, type = nil, options = {})
603
613
  execute "ALTER TABLE #{quote_table_name(table_name)} #{remove_column_for_alter(table_name, column_name, type, options)}"
604
614
  end
@@ -842,17 +852,17 @@ module ActiveRecord
842
852
  # [<tt>:null</tt>]
843
853
  # Whether the column allows nulls. Defaults to true.
844
854
  #
845
- # ====== Create a user_id bigint column
855
+ # ====== Create a user_id bigint column without a index
846
856
  #
847
- # add_reference(:products, :user)
857
+ # add_reference(:products, :user, index: false)
848
858
  #
849
859
  # ====== Create a user_id string column
850
860
  #
851
861
  # add_reference(:products, :user, type: :string)
852
862
  #
853
- # ====== Create supplier_id, supplier_type columns and appropriate index
863
+ # ====== Create supplier_id, supplier_type columns
854
864
  #
855
- # add_reference(:products, :supplier, polymorphic: true, index: true)
865
+ # add_reference(:products, :supplier, polymorphic: true)
856
866
  #
857
867
  # ====== Create a supplier_id column with a unique index
858
868
  #
@@ -880,7 +890,7 @@ module ActiveRecord
880
890
  #
881
891
  # ====== Remove the reference
882
892
  #
883
- # remove_reference(:products, :user, index: true)
893
+ # remove_reference(:products, :user, index: false)
884
894
  #
885
895
  # ====== Remove polymorphic reference
886
896
  #
@@ -888,7 +898,7 @@ module ActiveRecord
888
898
  #
889
899
  # ====== Remove the reference with a foreign key
890
900
  #
891
- # remove_reference(:products, :user, index: true, foreign_key: true)
901
+ # remove_reference(:products, :user, foreign_key: true)
892
902
  #
893
903
  def remove_reference(table_name, ref_name, foreign_key: false, polymorphic: false, **options)
894
904
  if foreign_key
@@ -980,11 +990,18 @@ module ActiveRecord
980
990
  #
981
991
  # remove_foreign_key :accounts, column: :owner_id
982
992
  #
993
+ # Removes the foreign key on +accounts.owner_id+.
994
+ #
995
+ # remove_foreign_key :accounts, to_table: :owners
996
+ #
983
997
  # Removes the foreign key named +special_fk_name+ on the +accounts+ table.
984
998
  #
985
999
  # remove_foreign_key :accounts, name: :special_fk_name
986
1000
  #
987
- # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key.
1001
+ # The +options+ hash accepts the same keys as SchemaStatements#add_foreign_key
1002
+ # with an addition of
1003
+ # [<tt>:to_table</tt>]
1004
+ # The name of the table that contains the referenced primary key.
988
1005
  def remove_foreign_key(from_table, options_or_to_table = {})
989
1006
  return unless supports_foreign_keys?
990
1007
 
@@ -1034,15 +1051,18 @@ module ActiveRecord
1034
1051
  { primary_key: true }
1035
1052
  end
1036
1053
 
1037
- def assume_migrated_upto_version(version, migrations_paths)
1038
- migrations_paths = Array(migrations_paths)
1054
+ def assume_migrated_upto_version(version, migrations_paths = nil)
1055
+ unless migrations_paths.nil?
1056
+ ActiveSupport::Deprecation.warn(<<~MSG)
1057
+ Passing migrations_paths to #assume_migrated_upto_version is deprecated and will be removed in Rails 6.1.
1058
+ MSG
1059
+ end
1060
+
1039
1061
  version = version.to_i
1040
1062
  sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1041
1063
 
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
1064
+ migrated = migration_context.get_all_versions
1065
+ versions = migration_context.migrations.map(&:version)
1046
1066
 
1047
1067
  unless migrated.include?(version)
1048
1068
  execute "INSERT INTO #{sm_table} (version) VALUES (#{quote(version)})"
@@ -1053,13 +1073,7 @@ module ActiveRecord
1053
1073
  if (duplicate = inserting.detect { |v| inserting.count(v) > 1 })
1054
1074
  raise "Duplicate migration #{duplicate}. Please renumber your migrations to resolve the conflict."
1055
1075
  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
1076
+ execute insert_versions_sql(inserting)
1063
1077
  end
1064
1078
  end
1065
1079
 
@@ -1375,7 +1389,7 @@ module ActiveRecord
1375
1389
  sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
1376
1390
 
1377
1391
  if versions.is_a?(Array)
1378
- sql = "INSERT INTO #{sm_table} (version) VALUES\n".dup
1392
+ sql = +"INSERT INTO #{sm_table} (version) VALUES\n"
1379
1393
  sql << versions.map { |v| "(#{quote(v)})" }.join(",\n")
1380
1394
  sql << ";\n\n"
1381
1395
  sql