activerecord 6.0.6.1 → 6.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (242) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +764 -942
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +3 -3
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +22 -14
  7. data/lib/active_record/associations/alias_tracker.rb +19 -15
  8. data/lib/active_record/associations/association.rb +39 -27
  9. data/lib/active_record/associations/association_scope.rb +11 -15
  10. data/lib/active_record/associations/belongs_to_association.rb +15 -5
  11. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
  12. data/lib/active_record/associations/builder/association.rb +9 -3
  13. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  14. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -1
  16. data/lib/active_record/associations/builder/has_many.rb +6 -2
  17. data/lib/active_record/associations/builder/has_one.rb +11 -14
  18. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  19. data/lib/active_record/associations/collection_association.rb +19 -13
  20. data/lib/active_record/associations/collection_proxy.rb +12 -5
  21. data/lib/active_record/associations/foreign_association.rb +13 -0
  22. data/lib/active_record/associations/has_many_association.rb +24 -2
  23. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  24. data/lib/active_record/associations/has_one_association.rb +15 -1
  25. data/lib/active_record/associations/join_dependency/join_association.rb +29 -14
  26. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  27. data/lib/active_record/associations/join_dependency.rb +63 -49
  28. data/lib/active_record/associations/preloader/association.rb +13 -5
  29. data/lib/active_record/associations/preloader/through_association.rb +1 -1
  30. data/lib/active_record/associations/preloader.rb +5 -3
  31. data/lib/active_record/associations/singular_association.rb +1 -1
  32. data/lib/active_record/associations.rb +114 -11
  33. data/lib/active_record/attribute_assignment.rb +10 -8
  34. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -9
  35. data/lib/active_record/attribute_methods/dirty.rb +1 -11
  36. data/lib/active_record/attribute_methods/primary_key.rb +6 -2
  37. data/lib/active_record/attribute_methods/query.rb +3 -6
  38. data/lib/active_record/attribute_methods/read.rb +8 -11
  39. data/lib/active_record/attribute_methods/serialization.rb +4 -4
  40. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -13
  41. data/lib/active_record/attribute_methods/write.rb +12 -20
  42. data/lib/active_record/attribute_methods.rb +52 -48
  43. data/lib/active_record/attributes.rb +27 -7
  44. data/lib/active_record/autosave_association.rb +47 -30
  45. data/lib/active_record/base.rb +2 -14
  46. data/lib/active_record/callbacks.rb +32 -22
  47. data/lib/active_record/coders/yaml_column.rb +2 -24
  48. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +180 -134
  49. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  50. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -22
  51. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -7
  52. data/lib/active_record/connection_adapters/abstract/quoting.rb +35 -44
  53. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  54. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -116
  55. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +110 -30
  56. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +224 -85
  58. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -24
  59. data/lib/active_record/connection_adapters/abstract_adapter.rb +31 -70
  60. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +123 -87
  61. data/lib/active_record/connection_adapters/column.rb +15 -1
  62. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  63. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  64. data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -24
  65. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -1
  66. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  67. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +33 -6
  68. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  69. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
  70. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +3 -3
  71. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  72. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -12
  73. data/lib/active_record/connection_adapters/pool_config.rb +63 -0
  74. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  75. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  76. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +12 -53
  77. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  78. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  79. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -10
  80. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  81. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -2
  82. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  84. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  88. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +61 -29
  91. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  92. data/lib/active_record/connection_adapters/postgresql_adapter.rb +72 -55
  93. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  94. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  95. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +30 -5
  96. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -1
  97. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  98. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +36 -3
  99. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +48 -50
  100. data/lib/active_record/connection_adapters.rb +50 -0
  101. data/lib/active_record/connection_handling.rb +210 -71
  102. data/lib/active_record/core.rb +214 -58
  103. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  104. data/lib/active_record/database_configurations/database_config.rb +52 -9
  105. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  106. data/lib/active_record/database_configurations/url_config.rb +15 -40
  107. data/lib/active_record/database_configurations.rb +124 -85
  108. data/lib/active_record/delegated_type.rb +209 -0
  109. data/lib/active_record/destroy_association_async_job.rb +36 -0
  110. data/lib/active_record/enum.rb +33 -23
  111. data/lib/active_record/errors.rb +47 -12
  112. data/lib/active_record/explain.rb +9 -4
  113. data/lib/active_record/explain_subscriber.rb +1 -1
  114. data/lib/active_record/fixture_set/file.rb +10 -17
  115. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  116. data/lib/active_record/fixture_set/render_context.rb +1 -1
  117. data/lib/active_record/fixture_set/table_row.rb +2 -2
  118. data/lib/active_record/fixtures.rb +54 -8
  119. data/lib/active_record/gem_version.rb +3 -3
  120. data/lib/active_record/inheritance.rb +40 -18
  121. data/lib/active_record/insert_all.rb +32 -5
  122. data/lib/active_record/integration.rb +3 -5
  123. data/lib/active_record/internal_metadata.rb +15 -4
  124. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  125. data/lib/active_record/locking/optimistic.rb +13 -16
  126. data/lib/active_record/locking/pessimistic.rb +6 -2
  127. data/lib/active_record/log_subscriber.rb +26 -8
  128. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  129. data/lib/active_record/middleware/database_selector/resolver.rb +5 -0
  130. data/lib/active_record/middleware/database_selector.rb +4 -1
  131. data/lib/active_record/migration/command_recorder.rb +47 -27
  132. data/lib/active_record/migration/compatibility.rb +67 -17
  133. data/lib/active_record/migration.rb +113 -83
  134. data/lib/active_record/model_schema.rb +88 -42
  135. data/lib/active_record/nested_attributes.rb +2 -3
  136. data/lib/active_record/no_touching.rb +1 -1
  137. data/lib/active_record/persistence.rb +50 -45
  138. data/lib/active_record/query_cache.rb +15 -5
  139. data/lib/active_record/querying.rb +11 -6
  140. data/lib/active_record/railtie.rb +64 -44
  141. data/lib/active_record/railties/databases.rake +253 -98
  142. data/lib/active_record/readonly_attributes.rb +4 -0
  143. data/lib/active_record/reflection.rb +59 -44
  144. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  145. data/lib/active_record/relation/batches.rb +38 -31
  146. data/lib/active_record/relation/calculations.rb +100 -43
  147. data/lib/active_record/relation/finder_methods.rb +44 -14
  148. data/lib/active_record/relation/from_clause.rb +1 -1
  149. data/lib/active_record/relation/merger.rb +20 -23
  150. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  151. data/lib/active_record/relation/predicate_builder/association_query_value.rb +2 -2
  152. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +3 -3
  153. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  154. data/lib/active_record/relation/predicate_builder.rb +57 -33
  155. data/lib/active_record/relation/query_methods.rb +319 -198
  156. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  157. data/lib/active_record/relation/spawn_methods.rb +6 -5
  158. data/lib/active_record/relation/where_clause.rb +104 -57
  159. data/lib/active_record/relation.rb +90 -64
  160. data/lib/active_record/result.rb +41 -33
  161. data/lib/active_record/runtime_registry.rb +2 -2
  162. data/lib/active_record/sanitization.rb +6 -17
  163. data/lib/active_record/schema_dumper.rb +34 -4
  164. data/lib/active_record/schema_migration.rb +0 -4
  165. data/lib/active_record/scoping/named.rb +1 -17
  166. data/lib/active_record/secure_token.rb +16 -8
  167. data/lib/active_record/serialization.rb +5 -3
  168. data/lib/active_record/signed_id.rb +116 -0
  169. data/lib/active_record/statement_cache.rb +20 -4
  170. data/lib/active_record/store.rb +2 -2
  171. data/lib/active_record/suppressor.rb +2 -2
  172. data/lib/active_record/table_metadata.rb +36 -52
  173. data/lib/active_record/tasks/database_tasks.rb +139 -113
  174. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -35
  175. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -26
  176. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -9
  177. data/lib/active_record/test_databases.rb +5 -4
  178. data/lib/active_record/test_fixtures.rb +36 -33
  179. data/lib/active_record/timestamp.rb +4 -6
  180. data/lib/active_record/touch_later.rb +21 -21
  181. data/lib/active_record/transactions.rb +15 -64
  182. data/lib/active_record/type/serialized.rb +6 -2
  183. data/lib/active_record/type.rb +8 -1
  184. data/lib/active_record/type_caster/connection.rb +0 -1
  185. data/lib/active_record/type_caster/map.rb +8 -5
  186. data/lib/active_record/validations/associated.rb +1 -1
  187. data/lib/active_record/validations/numericality.rb +35 -0
  188. data/lib/active_record/validations/uniqueness.rb +24 -4
  189. data/lib/active_record/validations.rb +1 -0
  190. data/lib/active_record.rb +7 -14
  191. data/lib/arel/attributes/attribute.rb +4 -0
  192. data/lib/arel/collectors/bind.rb +5 -0
  193. data/lib/arel/collectors/composite.rb +8 -0
  194. data/lib/arel/collectors/sql_string.rb +7 -0
  195. data/lib/arel/collectors/substitute_binds.rb +7 -0
  196. data/lib/arel/nodes/binary.rb +82 -8
  197. data/lib/arel/nodes/bind_param.rb +8 -0
  198. data/lib/arel/nodes/casted.rb +21 -9
  199. data/lib/arel/nodes/equality.rb +6 -9
  200. data/lib/arel/nodes/grouping.rb +3 -0
  201. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  202. data/lib/arel/nodes/in.rb +8 -1
  203. data/lib/arel/nodes/infix_operation.rb +13 -1
  204. data/lib/arel/nodes/join_source.rb +1 -1
  205. data/lib/arel/nodes/node.rb +7 -6
  206. data/lib/arel/nodes/ordering.rb +27 -0
  207. data/lib/arel/nodes/sql_literal.rb +3 -0
  208. data/lib/arel/nodes/table_alias.rb +7 -3
  209. data/lib/arel/nodes/unary.rb +0 -1
  210. data/lib/arel/nodes.rb +3 -1
  211. data/lib/arel/predications.rb +12 -18
  212. data/lib/arel/select_manager.rb +1 -2
  213. data/lib/arel/table.rb +13 -5
  214. data/lib/arel/visitors/dot.rb +14 -2
  215. data/lib/arel/visitors/mysql.rb +11 -1
  216. data/lib/arel/visitors/postgresql.rb +15 -4
  217. data/lib/arel/visitors/to_sql.rb +89 -78
  218. data/lib/arel/visitors.rb +0 -7
  219. data/lib/arel.rb +5 -13
  220. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  221. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  222. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +3 -3
  223. data/lib/rails/generators/active_record/migration.rb +6 -1
  224. data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
  225. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  226. metadata +30 -32
  227. data/lib/active_record/advisory_lock_base.rb +0 -18
  228. data/lib/active_record/attribute_decorators.rb +0 -88
  229. data/lib/active_record/connection_adapters/connection_specification.rb +0 -296
  230. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  231. data/lib/active_record/define_callbacks.rb +0 -22
  232. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  233. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  234. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  235. data/lib/arel/attributes.rb +0 -22
  236. data/lib/arel/visitors/depth_first.rb +0 -203
  237. data/lib/arel/visitors/ibm_db.rb +0 -34
  238. data/lib/arel/visitors/informix.rb +0 -62
  239. data/lib/arel/visitors/mssql.rb +0 -156
  240. data/lib/arel/visitors/oracle.rb +0 -158
  241. data/lib/arel/visitors/oracle12.rb +0 -65
  242. data/lib/arel/visitors/where_sql.rb +0 -22
@@ -2,89 +2,73 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class TableMetadata # :nodoc:
5
- delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
5
+ delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
6
6
 
7
- def initialize(klass, arel_table, association = nil, types = klass)
7
+ def initialize(klass, arel_table, reflection = nil)
8
8
  @klass = klass
9
- @types = types
10
9
  @arel_table = arel_table
11
- @association = association
12
- end
13
-
14
- def resolve_column_aliases(hash)
15
- new_hash = hash.dup
16
- hash.each_key do |key|
17
- if key.is_a?(Symbol) && new_key = klass.attribute_aliases[key.to_s]
18
- new_hash[new_key] = new_hash.delete(key)
19
- end
20
- end
21
- new_hash
22
- end
23
-
24
- def arel_attribute(column_name)
25
- if klass
26
- klass.arel_attribute(column_name, arel_table)
27
- else
28
- arel_table[column_name]
29
- end
10
+ @reflection = reflection
30
11
  end
31
12
 
32
13
  def type(column_name)
33
- types.type_for_attribute(column_name)
14
+ arel_table.type_for_attribute(column_name)
34
15
  end
35
16
 
36
17
  def has_column?(column_name)
37
- klass && klass.columns_hash.key?(column_name.to_s)
18
+ klass&.columns_hash.key?(column_name)
38
19
  end
39
20
 
40
- def associated_with?(association_name)
41
- klass && klass._reflect_on_association(association_name)
21
+ def associated_with?(table_name)
22
+ klass&._reflect_on_association(table_name) || klass&._reflect_on_association(table_name.singularize)
42
23
  end
43
24
 
44
25
  def associated_table(table_name)
45
- association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize)
26
+ reflection = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.singularize)
46
27
 
47
- if !association && table_name == arel_table.name
48
- self
49
- elsif association && !association.polymorphic?
50
- association_klass = association.klass
51
- arel_table = association_klass.arel_table.alias(table_name)
52
- TableMetadata.new(association_klass, arel_table, association)
28
+ if !reflection && table_name == arel_table.name
29
+ return self
30
+ end
31
+
32
+ reflection ||= yield table_name if block_given?
33
+
34
+ if reflection && !reflection.polymorphic?
35
+ association_klass = reflection.klass
36
+ arel_table = association_klass.arel_table
37
+ arel_table = arel_table.alias(table_name) if arel_table.name != table_name
38
+ TableMetadata.new(association_klass, arel_table, reflection)
53
39
  else
54
40
  type_caster = TypeCaster::Connection.new(klass, table_name)
55
41
  arel_table = Arel::Table.new(table_name, type_caster: type_caster)
56
- TableMetadata.new(nil, arel_table, association, type_caster)
42
+ TableMetadata.new(nil, arel_table, reflection)
57
43
  end
58
44
  end
59
45
 
60
- def associated_predicate_builder(table_name)
61
- associated_table(table_name).predicate_builder
62
- end
63
-
64
46
  def polymorphic_association?
65
- association && association.polymorphic?
47
+ reflection&.polymorphic?
66
48
  end
67
49
 
68
- def aggregated_with?(aggregation_name)
69
- klass && reflect_on_aggregation(aggregation_name)
50
+ def through_association?
51
+ reflection&.through_reflection?
70
52
  end
71
53
 
72
54
  def reflect_on_aggregation(aggregation_name)
73
- klass.reflect_on_aggregation(aggregation_name)
55
+ klass&.reflect_on_aggregation(aggregation_name)
74
56
  end
57
+ alias :aggregated_with? :reflect_on_aggregation
75
58
 
76
- protected
77
- def predicate_builder
78
- if klass
79
- predicate_builder = klass.predicate_builder.dup
80
- predicate_builder.instance_variable_set(:@table, self)
81
- predicate_builder
82
- else
83
- PredicateBuilder.new(self)
84
- end
59
+ def predicate_builder
60
+ if klass
61
+ predicate_builder = klass.predicate_builder.dup
62
+ predicate_builder.instance_variable_set(:@table, self)
63
+ predicate_builder
64
+ else
65
+ PredicateBuilder.new(self)
85
66
  end
67
+ end
68
+
69
+ attr_reader :arel_table
86
70
 
87
71
  private
88
- attr_reader :klass, :types, :arel_table, :association
72
+ attr_reader :klass, :reflection
89
73
  end
90
74
  end
@@ -4,7 +4,6 @@ require "active_record/database_configurations"
4
4
 
5
5
  module ActiveRecord
6
6
  module Tasks # :nodoc:
7
- class DatabaseAlreadyExists < StandardError; end # :nodoc:
8
7
  class DatabaseNotSupported < StandardError; end # :nodoc:
9
8
 
10
9
  # ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
@@ -39,17 +38,18 @@ module ActiveRecord
39
38
  module DatabaseTasks
40
39
  ##
41
40
  # :singleton-method:
42
- # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:structure:dump
41
+ # Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
43
42
  mattr_accessor :structure_dump_flags, instance_accessor: false
44
43
 
45
44
  ##
46
45
  # :singleton-method:
47
- # Extra flags passed to database CLI tool when calling db:structure:load
46
+ # Extra flags passed to database CLI tool when calling db:schema:load
48
47
  mattr_accessor :structure_load_flags, instance_accessor: false
49
48
 
50
49
  extend self
51
50
 
52
51
  attr_writer :current_config, :db_dir, :migrations_paths, :fixtures_path, :root, :env, :seed_loader
52
+ deprecate :current_config=
53
53
  attr_accessor :database_configuration
54
54
 
55
55
  LOCAL_HOSTS = ["127.0.0.1", "localhost"]
@@ -106,38 +106,45 @@ module ActiveRecord
106
106
  def spec
107
107
  @spec ||= "primary"
108
108
  end
109
+ deprecate spec: "please use name instead"
110
+
111
+ def name
112
+ @name ||= "primary"
113
+ end
109
114
 
110
115
  def seed_loader
111
116
  @seed_loader ||= Rails.application
112
117
  end
113
118
 
114
119
  def current_config(options = {})
115
- options.reverse_merge! env: env
116
- options[:spec] ||= "primary"
117
120
  if options.has_key?(:config)
118
121
  @current_config = options[:config]
119
122
  else
120
- @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: options[:env], spec_name: options[:spec]).config
123
+ env_name = options[:env] || env
124
+ name = options[:spec] || "primary"
125
+
126
+ @current_config ||= ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: name)&.configuration_hash
121
127
  end
122
128
  end
129
+ deprecate :current_config
123
130
 
124
- def create(*arguments)
125
- configuration = arguments.first
126
- class_for_adapter(configuration["adapter"]).new(*arguments).create
127
- $stdout.puts "Created database '#{configuration['database']}'" if verbose?
131
+ def create(configuration, *arguments)
132
+ db_config = resolve_configuration(configuration)
133
+ database_adapter_for(db_config, *arguments).create
134
+ $stdout.puts "Created database '#{db_config.database}'" if verbose?
128
135
  rescue DatabaseAlreadyExists
129
- $stderr.puts "Database '#{configuration['database']}' already exists" if verbose?
136
+ $stderr.puts "Database '#{db_config.database}' already exists" if verbose?
130
137
  rescue Exception => error
131
138
  $stderr.puts error
132
- $stderr.puts "Couldn't create '#{configuration['database']}' database. Please check your configuration."
139
+ $stderr.puts "Couldn't create '#{db_config.database}' database. Please check your configuration."
133
140
  raise
134
141
  end
135
142
 
136
143
  def create_all
137
144
  old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name)
138
- each_local_configuration { |configuration| create configuration }
145
+ each_local_configuration { |db_config| create(db_config) }
139
146
  if old_pool
140
- ActiveRecord::Base.connection_handler.establish_connection(old_pool.spec.to_hash)
147
+ ActiveRecord::Base.connection_handler.establish_connection(old_pool.db_config)
141
148
  end
142
149
  end
143
150
 
@@ -147,7 +154,9 @@ module ActiveRecord
147
154
  begin
148
155
  Rails.application.config.load_database_yaml
149
156
  rescue
150
- $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
157
+ unless ActiveRecord::Base.suppress_multiple_database_warning
158
+ $stderr.puts "Rails couldn't infer whether you are using multiple databases from your database.yml and can't generate the tasks for the non-primary databases. If you'd like to use this feature, please simplify your ERB."
159
+ end
151
160
 
152
161
  {}
153
162
  end
@@ -162,7 +171,7 @@ module ActiveRecord
162
171
  return if database_configs.count == 1
163
172
 
164
173
  database_configs.each do |db_config|
165
- yield db_config.spec_name
174
+ yield db_config.name
166
175
  end
167
176
  end
168
177
 
@@ -173,59 +182,49 @@ module ActiveRecord
173
182
  dbs_list = []
174
183
 
175
184
  db_configs.each do |db|
176
- dbs_list << "#{command}:#{db.spec_name}"
185
+ dbs_list << "#{command}:#{db.name}"
177
186
  end
178
187
 
179
188
  raise "You're using a multiple database application. To use `#{command}` you must run the namespaced task with a VERSION. Available tasks are #{dbs_list.to_sentence}."
180
189
  end
181
190
  end
182
191
 
183
- def create_current(environment = env, spec_name = nil)
184
- each_current_configuration(environment, spec_name) { |configuration|
185
- create configuration
186
- }
192
+ def create_current(environment = env, name = nil)
193
+ each_current_configuration(environment, name) { |db_config| create(db_config) }
187
194
  ActiveRecord::Base.establish_connection(environment.to_sym)
188
195
  end
189
196
 
190
- def drop(*arguments)
191
- configuration = arguments.first
192
- class_for_adapter(configuration["adapter"]).new(*arguments).drop
193
- $stdout.puts "Dropped database '#{configuration['database']}'" if verbose?
197
+ def drop(configuration, *arguments)
198
+ db_config = resolve_configuration(configuration)
199
+ database_adapter_for(db_config, *arguments).drop
200
+ $stdout.puts "Dropped database '#{db_config.database}'" if verbose?
194
201
  rescue ActiveRecord::NoDatabaseError
195
- $stderr.puts "Database '#{configuration['database']}' does not exist"
202
+ $stderr.puts "Database '#{db_config.database}' does not exist"
196
203
  rescue Exception => error
197
204
  $stderr.puts error
198
- $stderr.puts "Couldn't drop database '#{configuration['database']}'"
205
+ $stderr.puts "Couldn't drop database '#{db_config.database}'"
199
206
  raise
200
207
  end
201
208
 
202
209
  def drop_all
203
- each_local_configuration { |configuration| drop configuration }
210
+ each_local_configuration { |db_config| drop(db_config) }
204
211
  end
205
212
 
206
213
  def drop_current(environment = env)
207
- each_current_configuration(environment) { |configuration|
208
- drop configuration
209
- }
214
+ each_current_configuration(environment) { |db_config| drop(db_config) }
210
215
  end
211
216
 
212
- def truncate_tables(configuration)
213
- ActiveRecord::Base.connected_to(database: { truncation: configuration }) do
214
- conn = ActiveRecord::Base.connection
215
- table_names = conn.tables
216
- table_names -= [
217
- conn.schema_migration.table_name,
218
- InternalMetadata.table_name
219
- ]
217
+ def truncate_tables(db_config)
218
+ ActiveRecord::Base.establish_connection(db_config)
220
219
 
221
- ActiveRecord::Base.connection.truncate_tables(*table_names)
222
- end
220
+ connection = ActiveRecord::Base.connection
221
+ connection.truncate_tables(*connection.tables)
223
222
  end
224
223
  private :truncate_tables
225
224
 
226
225
  def truncate_all(environment = env)
227
226
  ActiveRecord::Base.configurations.configs_for(env_name: environment).each do |db_config|
228
- truncate_tables db_config.config
227
+ truncate_tables(db_config)
229
228
  end
230
229
  end
231
230
 
@@ -250,7 +249,7 @@ module ActiveRecord
250
249
  end
251
250
 
252
251
  # output
253
- puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
252
+ puts "\ndatabase: #{ActiveRecord::Base.connection_db_config.database}\n\n"
254
253
  puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
255
254
  puts "-" * 50
256
255
  ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
@@ -269,106 +268,116 @@ module ActiveRecord
269
268
  ENV["VERSION"].to_i if ENV["VERSION"] && !ENV["VERSION"].empty?
270
269
  end
271
270
 
272
- def charset_current(environment = env, specification_name = spec)
273
- charset ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
271
+ def charset_current(env_name = env, db_name = name)
272
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
273
+ charset(db_config)
274
274
  end
275
275
 
276
- def charset(*arguments)
277
- configuration = arguments.first
278
- class_for_adapter(configuration["adapter"]).new(*arguments).charset
276
+ def charset(configuration, *arguments)
277
+ db_config = resolve_configuration(configuration)
278
+ database_adapter_for(db_config, *arguments).charset
279
279
  end
280
280
 
281
- def collation_current(environment = env, specification_name = spec)
282
- collation ActiveRecord::Base.configurations.configs_for(env_name: environment, spec_name: specification_name).config
281
+ def collation_current(env_name = env, db_name = name)
282
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: env_name, name: db_name)
283
+ collation(db_config)
283
284
  end
284
285
 
285
- def collation(*arguments)
286
- configuration = arguments.first
287
- class_for_adapter(configuration["adapter"]).new(*arguments).collation
286
+ def collation(configuration, *arguments)
287
+ db_config = resolve_configuration(configuration)
288
+ database_adapter_for(db_config, *arguments).collation
288
289
  end
289
290
 
290
291
  def purge(configuration)
291
- class_for_adapter(configuration["adapter"]).new(configuration).purge
292
+ db_config = resolve_configuration(configuration)
293
+ database_adapter_for(db_config).purge
292
294
  end
293
295
 
294
296
  def purge_all
295
- each_local_configuration { |configuration|
296
- purge configuration
297
- }
297
+ each_local_configuration { |db_config| purge(db_config) }
298
298
  end
299
299
 
300
300
  def purge_current(environment = env)
301
- each_current_configuration(environment) { |configuration|
302
- purge configuration
303
- }
301
+ each_current_configuration(environment) { |db_config| purge(db_config) }
304
302
  ActiveRecord::Base.establish_connection(environment.to_sym)
305
303
  end
306
304
 
307
- def structure_dump(*arguments)
308
- configuration = arguments.first
309
- filename = arguments.delete_at 1
310
- class_for_adapter(configuration["adapter"]).new(*arguments).structure_dump(filename, structure_dump_flags)
305
+ def structure_dump(configuration, *arguments)
306
+ db_config = resolve_configuration(configuration)
307
+ filename = arguments.delete_at(0)
308
+ database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
311
309
  end
312
310
 
313
- def structure_load(*arguments)
314
- configuration = arguments.first
315
- filename = arguments.delete_at 1
316
- class_for_adapter(configuration["adapter"]).new(*arguments).structure_load(filename, structure_load_flags)
311
+ def structure_load(configuration, *arguments)
312
+ db_config = resolve_configuration(configuration)
313
+ filename = arguments.delete_at(0)
314
+ database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
317
315
  end
318
316
 
319
- def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
320
- file ||= dump_filename(spec_name, format)
317
+ def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
318
+ file ||= dump_filename(db_config.name, format)
321
319
 
322
320
  verbose_was, Migration.verbose = Migration.verbose, verbose? && ENV["VERBOSE"]
323
321
  check_schema_file(file)
324
- ActiveRecord::Base.establish_connection(configuration)
322
+ ActiveRecord::Base.establish_connection(db_config)
325
323
 
326
324
  case format
327
325
  when :ruby
328
326
  load(file)
329
327
  when :sql
330
- structure_load(configuration, file)
328
+ structure_load(db_config, file)
331
329
  else
332
330
  raise ArgumentError, "unknown format #{format.inspect}"
333
331
  end
334
332
  ActiveRecord::InternalMetadata.create_table
335
- ActiveRecord::InternalMetadata[:environment] = environment
333
+ ActiveRecord::InternalMetadata[:environment] = db_config.env_name
336
334
  ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
337
335
  ensure
338
336
  Migration.verbose = verbose_was
339
337
  end
340
338
 
341
- def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
342
- file ||= dump_filename(spec_name, format)
339
+ def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = nil, name = nil)
340
+ db_config = resolve_configuration(configuration)
341
+
342
+ if environment || name
343
+ ActiveSupport::Deprecation.warn("`environment` and `name` will be removed as parameters in 6.2.0, you may now pass an ActiveRecord::DatabaseConfigurations::DatabaseConfig as `configuration` instead.")
344
+ end
345
+
346
+ name ||= db_config.name
347
+
348
+ file ||= dump_filename(name, format)
343
349
 
344
350
  return true unless File.exist?(file)
345
351
 
346
- ActiveRecord::Base.establish_connection(configuration)
352
+ ActiveRecord::Base.establish_connection(db_config)
353
+
354
+ return false unless ActiveRecord::InternalMetadata.enabled?
347
355
  return false unless ActiveRecord::InternalMetadata.table_exists?
356
+
348
357
  ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
349
358
  end
350
359
 
351
- def reconstruct_from_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary") # :nodoc:
352
- file ||= dump_filename(spec_name, format)
360
+ def reconstruct_from_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
361
+ file ||= dump_filename(db_config.name, format)
353
362
 
354
363
  check_schema_file(file)
355
364
 
356
- ActiveRecord::Base.establish_connection(configuration)
365
+ ActiveRecord::Base.establish_connection(db_config)
357
366
 
358
- if schema_up_to_date?(configuration, format, file, environment, spec_name)
359
- truncate_tables(configuration)
367
+ if schema_up_to_date?(db_config, format, file)
368
+ truncate_tables(db_config)
360
369
  else
361
- purge(configuration)
362
- load_schema(configuration, format, file, environment, spec_name)
370
+ purge(db_config)
371
+ load_schema(db_config, format, file)
363
372
  end
364
373
  rescue ActiveRecord::NoDatabaseError
365
- create(configuration)
366
- load_schema(configuration, format, file, environment, spec_name)
374
+ create(db_config)
375
+ load_schema(db_config, format, file)
367
376
  end
368
377
 
369
- def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
378
+ def dump_schema(db_config, format = ActiveRecord::Base.schema_format) # :nodoc:
370
379
  require "active_record/schema_dumper"
371
- filename = dump_filename(spec_name, format)
380
+ filename = dump_filename(db_config.name, format)
372
381
  connection = ActiveRecord::Base.connection
373
382
 
374
383
  case format
@@ -377,7 +386,7 @@ module ActiveRecord
377
386
  ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
378
387
  end
379
388
  when :sql
380
- structure_dump(configuration, filename)
389
+ structure_dump(db_config, filename)
381
390
  if connection.schema_migration.table_exists?
382
391
  File.open(filename, "a") do |f|
383
392
  f.puts connection.dump_schema_information
@@ -400,36 +409,36 @@ module ActiveRecord
400
409
  end
401
410
  end
402
411
 
403
- def dump_filename(namespace, format = ActiveRecord::Base.schema_format)
404
- filename = if namespace == "primary"
412
+ def dump_filename(db_config_name, format = ActiveRecord::Base.schema_format)
413
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
405
414
  schema_file_type(format)
406
415
  else
407
- "#{namespace}_#{schema_file_type(format)}"
416
+ "#{db_config_name}_#{schema_file_type(format)}"
408
417
  end
409
418
 
410
419
  ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
411
420
  end
412
421
 
413
- def cache_dump_filename(namespace)
414
- filename = if namespace == "primary"
422
+ def cache_dump_filename(db_config_name, schema_cache_path: nil)
423
+ filename = if ActiveRecord::Base.configurations.primary?(db_config_name)
415
424
  "schema_cache.yml"
416
425
  else
417
- "#{namespace}_schema_cache.yml"
426
+ "#{db_config_name}_schema_cache.yml"
418
427
  end
419
428
 
420
- ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
429
+ schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
421
430
  end
422
431
 
423
432
  def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
424
- each_current_configuration(environment) { |configuration, spec_name, env|
425
- load_schema(configuration, format, file, env, spec_name)
426
- }
433
+ each_current_configuration(environment) do |db_config|
434
+ load_schema(db_config, format, file)
435
+ end
427
436
  ActiveRecord::Base.establish_connection(environment.to_sym)
428
437
  end
429
438
 
430
439
  def check_schema_file(filename)
431
440
  unless File.exist?(filename)
432
- message = +%{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
441
+ message = +%{#{filename} doesn't exist yet. Run `bin/rails db:migrate` to create it, then try again.}
433
442
  message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails.root)
434
443
  Kernel.abort message
435
444
  end
@@ -450,16 +459,33 @@ module ActiveRecord
450
459
  # ==== Examples:
451
460
  # ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, "tmp/schema_dump.yaml")
452
461
  def dump_schema_cache(conn, filename)
453
- conn.schema_cache.clear!
454
- conn.data_sources.each { |table| conn.schema_cache.add(table) }
455
- open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
462
+ conn.schema_cache.dump_to(filename)
463
+ end
464
+
465
+ def clear_schema_cache(filename)
466
+ FileUtils.rm_f filename, verbose: false
456
467
  end
457
468
 
458
469
  private
470
+ def resolve_configuration(configuration)
471
+ Base.configurations.resolve(configuration)
472
+ end
473
+
459
474
  def verbose?
460
475
  ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
461
476
  end
462
477
 
478
+ # Create a new instance for the specified db configuration object
479
+ # For classes that have been converted to use db_config objects, pass a
480
+ # `DatabaseConfig`, otherwise pass a `Hash`
481
+ def database_adapter_for(db_config, *arguments)
482
+ klass = class_for_adapter(db_config.adapter)
483
+ converted = klass.respond_to?(:using_database_configurations?) && klass.using_database_configurations?
484
+
485
+ config = converted ? db_config : db_config.configuration_hash
486
+ klass.new(config, *arguments)
487
+ end
488
+
463
489
  def class_for_adapter(adapter)
464
490
  _key, task = @tasks.each_pair.detect { |pattern, _task| adapter[pattern] }
465
491
  unless task
@@ -468,34 +494,34 @@ module ActiveRecord
468
494
  task.is_a?(String) ? task.constantize : task
469
495
  end
470
496
 
471
- def each_current_configuration(environment, spec_name = nil)
497
+ def each_current_configuration(environment, name = nil)
472
498
  environments = [environment]
473
- environments << "test" if environment == "development"
499
+ environments << "test" if environment == "development" && !ENV["SKIP_TEST_DATABASE"] && !ENV["DATABASE_URL"]
474
500
 
475
501
  environments.each do |env|
476
502
  ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config|
477
- next if spec_name && spec_name != db_config.spec_name
503
+ next if name && name != db_config.name
478
504
 
479
- yield db_config.config, db_config.spec_name, env
505
+ yield db_config
480
506
  end
481
507
  end
482
508
  end
483
509
 
484
510
  def each_local_configuration
485
511
  ActiveRecord::Base.configurations.configs_for.each do |db_config|
486
- configuration = db_config.config
487
- next unless configuration["database"]
512
+ next unless db_config.database
488
513
 
489
- if local_database?(configuration)
490
- yield configuration
514
+ if local_database?(db_config)
515
+ yield db_config
491
516
  else
492
- $stderr.puts "This task only modifies local databases. #{configuration['database']} is on a remote host."
517
+ $stderr.puts "This task only modifies local databases. #{db_config.database} is on a remote host."
493
518
  end
494
519
  end
495
520
  end
496
521
 
497
- def local_database?(configuration)
498
- configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
522
+ def local_database?(db_config)
523
+ host = db_config.host
524
+ host.blank? || LOCAL_HOSTS.include?(host)
499
525
  end
500
526
 
501
527
  def schema_sha1(file)