activerecord 7.1.3.4 → 7.2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +652 -2032
  3. data/README.rdoc +15 -15
  4. data/examples/performance.rb +2 -2
  5. data/lib/active_record/association_relation.rb +1 -1
  6. data/lib/active_record/associations/alias_tracker.rb +25 -19
  7. data/lib/active_record/associations/association.rb +15 -8
  8. data/lib/active_record/associations/belongs_to_association.rb +18 -11
  9. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +3 -2
  10. data/lib/active_record/associations/builder/belongs_to.rb +1 -0
  11. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +2 -2
  12. data/lib/active_record/associations/builder/has_many.rb +3 -4
  13. data/lib/active_record/associations/builder/has_one.rb +3 -4
  14. data/lib/active_record/associations/collection_association.rb +11 -5
  15. data/lib/active_record/associations/collection_proxy.rb +14 -1
  16. data/lib/active_record/associations/errors.rb +265 -0
  17. data/lib/active_record/associations/has_many_association.rb +3 -3
  18. data/lib/active_record/associations/has_many_through_association.rb +7 -1
  19. data/lib/active_record/associations/has_one_association.rb +2 -2
  20. data/lib/active_record/associations/join_dependency/join_association.rb +30 -27
  21. data/lib/active_record/associations/join_dependency.rb +10 -12
  22. data/lib/active_record/associations/nested_error.rb +47 -0
  23. data/lib/active_record/associations/preloader/association.rb +2 -1
  24. data/lib/active_record/associations/preloader/branch.rb +7 -1
  25. data/lib/active_record/associations/preloader/through_association.rb +1 -3
  26. data/lib/active_record/associations/singular_association.rb +6 -0
  27. data/lib/active_record/associations/through_association.rb +1 -1
  28. data/lib/active_record/associations.rb +62 -289
  29. data/lib/active_record/attribute_assignment.rb +0 -2
  30. data/lib/active_record/attribute_methods/composite_primary_key.rb +84 -0
  31. data/lib/active_record/attribute_methods/dirty.rb +2 -2
  32. data/lib/active_record/attribute_methods/primary_key.rb +23 -55
  33. data/lib/active_record/attribute_methods/read.rb +4 -16
  34. data/lib/active_record/attribute_methods/serialization.rb +4 -24
  35. data/lib/active_record/attribute_methods/time_zone_conversion.rb +11 -6
  36. data/lib/active_record/attribute_methods/write.rb +3 -3
  37. data/lib/active_record/attribute_methods.rb +89 -58
  38. data/lib/active_record/attributes.rb +61 -47
  39. data/lib/active_record/autosave_association.rb +17 -31
  40. data/lib/active_record/base.rb +2 -3
  41. data/lib/active_record/callbacks.rb +1 -1
  42. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +24 -107
  43. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +1 -0
  44. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +270 -58
  45. data/lib/active_record/connection_adapters/abstract/database_statements.rb +35 -18
  46. data/lib/active_record/connection_adapters/abstract/query_cache.rb +190 -75
  47. data/lib/active_record/connection_adapters/abstract/quoting.rb +65 -91
  48. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +1 -1
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +23 -10
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +125 -62
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +38 -59
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +73 -19
  53. data/lib/active_record/connection_adapters/mysql/database_statements.rb +9 -1
  54. data/lib/active_record/connection_adapters/mysql/quoting.rb +43 -48
  55. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +8 -1
  56. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +16 -15
  57. data/lib/active_record/connection_adapters/mysql2_adapter.rb +20 -32
  58. data/lib/active_record/connection_adapters/pool_config.rb +7 -6
  59. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +27 -4
  60. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  61. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +1 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +14 -4
  63. data/lib/active_record/connection_adapters/postgresql/quoting.rb +58 -58
  64. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +20 -0
  65. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +18 -12
  66. data/lib/active_record/connection_adapters/postgresql_adapter.rb +29 -24
  67. data/lib/active_record/connection_adapters/schema_cache.rb +123 -128
  68. data/lib/active_record/connection_adapters/sqlite3/column.rb +14 -1
  69. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +10 -6
  70. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +44 -46
  71. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  72. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +13 -0
  73. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +16 -0
  74. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +25 -2
  75. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +127 -77
  76. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +15 -15
  77. data/lib/active_record/connection_adapters/trilogy_adapter.rb +32 -65
  78. data/lib/active_record/connection_adapters.rb +121 -0
  79. data/lib/active_record/connection_handling.rb +56 -41
  80. data/lib/active_record/core.rb +93 -40
  81. data/lib/active_record/counter_cache.rb +23 -10
  82. data/lib/active_record/database_configurations/connection_url_resolver.rb +8 -3
  83. data/lib/active_record/database_configurations/database_config.rb +19 -4
  84. data/lib/active_record/database_configurations/hash_config.rb +44 -36
  85. data/lib/active_record/database_configurations/url_config.rb +20 -1
  86. data/lib/active_record/database_configurations.rb +1 -1
  87. data/lib/active_record/delegated_type.rb +30 -6
  88. data/lib/active_record/destroy_association_async_job.rb +1 -1
  89. data/lib/active_record/dynamic_matchers.rb +2 -2
  90. data/lib/active_record/encryption/encryptable_record.rb +3 -3
  91. data/lib/active_record/encryption/encrypted_attribute_type.rb +26 -6
  92. data/lib/active_record/encryption/encryptor.rb +18 -3
  93. data/lib/active_record/encryption/key_provider.rb +1 -1
  94. data/lib/active_record/encryption/message_pack_message_serializer.rb +76 -0
  95. data/lib/active_record/encryption/message_serializer.rb +4 -0
  96. data/lib/active_record/encryption/null_encryptor.rb +4 -0
  97. data/lib/active_record/encryption/read_only_null_encryptor.rb +4 -0
  98. data/lib/active_record/encryption/scheme.rb +8 -4
  99. data/lib/active_record/encryption.rb +2 -0
  100. data/lib/active_record/enum.rb +19 -2
  101. data/lib/active_record/errors.rb +46 -20
  102. data/lib/active_record/explain.rb +13 -24
  103. data/lib/active_record/fixtures.rb +37 -31
  104. data/lib/active_record/future_result.rb +17 -4
  105. data/lib/active_record/gem_version.rb +3 -3
  106. data/lib/active_record/inheritance.rb +4 -2
  107. data/lib/active_record/insert_all.rb +18 -15
  108. data/lib/active_record/integration.rb +4 -1
  109. data/lib/active_record/internal_metadata.rb +48 -34
  110. data/lib/active_record/locking/optimistic.rb +8 -7
  111. data/lib/active_record/log_subscriber.rb +0 -21
  112. data/lib/active_record/marshalling.rb +4 -1
  113. data/lib/active_record/message_pack.rb +2 -2
  114. data/lib/active_record/migration/command_recorder.rb +2 -3
  115. data/lib/active_record/migration/compatibility.rb +11 -3
  116. data/lib/active_record/migration/default_strategy.rb +4 -5
  117. data/lib/active_record/migration/pending_migration_connection.rb +2 -2
  118. data/lib/active_record/migration.rb +85 -76
  119. data/lib/active_record/model_schema.rb +38 -70
  120. data/lib/active_record/nested_attributes.rb +24 -5
  121. data/lib/active_record/normalization.rb +3 -7
  122. data/lib/active_record/persistence.rb +32 -354
  123. data/lib/active_record/query_cache.rb +19 -8
  124. data/lib/active_record/query_logs.rb +15 -0
  125. data/lib/active_record/query_logs_formatter.rb +1 -1
  126. data/lib/active_record/querying.rb +21 -9
  127. data/lib/active_record/railtie.rb +50 -68
  128. data/lib/active_record/railties/controller_runtime.rb +13 -4
  129. data/lib/active_record/railties/databases.rake +42 -45
  130. data/lib/active_record/reflection.rb +106 -38
  131. data/lib/active_record/relation/batches/batch_enumerator.rb +15 -2
  132. data/lib/active_record/relation/batches.rb +14 -8
  133. data/lib/active_record/relation/calculations.rb +96 -63
  134. data/lib/active_record/relation/delegation.rb +8 -11
  135. data/lib/active_record/relation/finder_methods.rb +16 -2
  136. data/lib/active_record/relation/merger.rb +4 -6
  137. data/lib/active_record/relation/predicate_builder/array_handler.rb +2 -2
  138. data/lib/active_record/relation/predicate_builder/association_query_value.rb +9 -3
  139. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
  140. data/lib/active_record/relation/predicate_builder.rb +3 -3
  141. data/lib/active_record/relation/query_methods.rb +245 -65
  142. data/lib/active_record/relation/record_fetch_warning.rb +3 -0
  143. data/lib/active_record/relation/spawn_methods.rb +2 -18
  144. data/lib/active_record/relation/where_clause.rb +7 -19
  145. data/lib/active_record/relation.rb +500 -66
  146. data/lib/active_record/result.rb +32 -45
  147. data/lib/active_record/runtime_registry.rb +39 -0
  148. data/lib/active_record/sanitization.rb +24 -19
  149. data/lib/active_record/schema.rb +8 -6
  150. data/lib/active_record/schema_dumper.rb +19 -9
  151. data/lib/active_record/schema_migration.rb +30 -14
  152. data/lib/active_record/scoping/named.rb +1 -0
  153. data/lib/active_record/signed_id.rb +20 -1
  154. data/lib/active_record/statement_cache.rb +7 -7
  155. data/lib/active_record/table_metadata.rb +1 -10
  156. data/lib/active_record/tasks/database_tasks.rb +98 -48
  157. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  158. data/lib/active_record/tasks/postgresql_database_tasks.rb +1 -1
  159. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -1
  160. data/lib/active_record/test_fixtures.rb +87 -89
  161. data/lib/active_record/testing/query_assertions.rb +121 -0
  162. data/lib/active_record/timestamp.rb +5 -3
  163. data/lib/active_record/token_for.rb +22 -12
  164. data/lib/active_record/touch_later.rb +1 -1
  165. data/lib/active_record/transaction.rb +132 -0
  166. data/lib/active_record/transactions.rb +70 -14
  167. data/lib/active_record/translation.rb +0 -2
  168. data/lib/active_record/type/serialized.rb +1 -3
  169. data/lib/active_record/type_caster/connection.rb +4 -4
  170. data/lib/active_record/validations/associated.rb +9 -3
  171. data/lib/active_record/validations/uniqueness.rb +15 -10
  172. data/lib/active_record/validations.rb +4 -1
  173. data/lib/active_record.rb +150 -41
  174. data/lib/arel/alias_predication.rb +1 -1
  175. data/lib/arel/collectors/bind.rb +2 -0
  176. data/lib/arel/collectors/composite.rb +7 -0
  177. data/lib/arel/collectors/sql_string.rb +1 -1
  178. data/lib/arel/collectors/substitute_binds.rb +1 -1
  179. data/lib/arel/nodes/binary.rb +0 -6
  180. data/lib/arel/nodes/bound_sql_literal.rb +9 -5
  181. data/lib/arel/nodes/{and.rb → nary.rb} +5 -2
  182. data/lib/arel/nodes/node.rb +4 -3
  183. data/lib/arel/nodes/sql_literal.rb +7 -0
  184. data/lib/arel/nodes.rb +2 -2
  185. data/lib/arel/predications.rb +1 -1
  186. data/lib/arel/select_manager.rb +1 -1
  187. data/lib/arel/tree_manager.rb +8 -3
  188. data/lib/arel/update_manager.rb +2 -1
  189. data/lib/arel/visitors/dot.rb +1 -0
  190. data/lib/arel/visitors/mysql.rb +9 -4
  191. data/lib/arel/visitors/postgresql.rb +1 -12
  192. data/lib/arel/visitors/sqlite.rb +25 -0
  193. data/lib/arel/visitors/to_sql.rb +31 -17
  194. data/lib/arel.rb +7 -3
  195. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +4 -1
  196. metadata +21 -15
@@ -10,15 +10,16 @@ module ActiveRecord
10
10
  :first_or_create, :first_or_create!, :first_or_initialize,
11
11
  :find_or_create_by, :find_or_create_by!, :find_or_initialize_by,
12
12
  :create_or_find_by, :create_or_find_by!,
13
- :destroy_all, :delete_all, :update_all, :touch_all, :destroy_by, :delete_by,
13
+ :destroy, :destroy_all, :delete, :delete_all, :update_all, :touch_all, :destroy_by, :delete_by,
14
14
  :find_each, :find_in_batches, :in_batches,
15
15
  :select, :reselect, :order, :regroup, :in_order_of, :reorder, :group, :limit, :offset, :joins, :left_joins, :left_outer_joins,
16
16
  :where, :rewhere, :invert_where, :preload, :extract_associated, :eager_load, :includes, :from, :lock, :readonly,
17
17
  :and, :or, :annotate, :optimizer_hints, :extending,
18
18
  :having, :create_with, :distinct, :references, :none, :unscope, :merge, :except, :only,
19
19
  :count, :average, :minimum, :maximum, :sum, :calculate,
20
- :pluck, :pick, :ids, :async_ids, :strict_loading, :excluding, :without, :with,
20
+ :pluck, :pick, :ids, :async_ids, :strict_loading, :excluding, :without, :with, :with_recursive,
21
21
  :async_count, :async_average, :async_minimum, :async_maximum, :async_sum, :async_pluck, :async_pick,
22
+ :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all
22
23
  ].freeze # :nodoc:
23
24
  delegate(*QUERYING_METHODS, to: :all)
24
25
 
@@ -47,19 +48,26 @@ module ActiveRecord
47
48
  #
48
49
  # Note that building your own SQL query string from user input may expose your application to
49
50
  # injection attacks (https://guides.rubyonrails.org/security.html#sql-injection).
50
- def find_by_sql(sql, binds = [], preparable: nil, &block)
51
- _load_from_sql(_query_by_sql(sql, binds, preparable: preparable), &block)
51
+ def find_by_sql(sql, binds = [], preparable: nil, allow_retry: false, &block)
52
+ result = with_connection do |c|
53
+ _query_by_sql(c, sql, binds, preparable: preparable, allow_retry: allow_retry)
54
+ end
55
+ _load_from_sql(result, &block)
52
56
  end
53
57
 
54
58
  # Same as <tt>#find_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
55
59
  def async_find_by_sql(sql, binds = [], preparable: nil, &block)
56
- _query_by_sql(sql, binds, preparable: preparable, async: true).then do |result|
60
+ result = with_connection do |c|
61
+ _query_by_sql(c, sql, binds, preparable: preparable, async: true)
62
+ end
63
+
64
+ result.then do |result|
57
65
  _load_from_sql(result, &block)
58
66
  end
59
67
  end
60
68
 
61
- def _query_by_sql(sql, binds = [], preparable: nil, async: false) # :nodoc:
62
- connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable, async: async)
69
+ def _query_by_sql(connection, sql, binds = [], preparable: nil, async: false, allow_retry: false) # :nodoc:
70
+ connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable, async: async, allow_retry: allow_retry)
63
71
  end
64
72
 
65
73
  def _load_from_sql(result_set, &block) # :nodoc:
@@ -99,12 +107,16 @@ module ActiveRecord
99
107
  #
100
108
  # * +sql+ - An SQL statement which should return a count query from the database, see the example above.
101
109
  def count_by_sql(sql)
102
- connection.select_value(sanitize_sql(sql), "#{name} Count").to_i
110
+ with_connection do |c|
111
+ c.select_value(sanitize_sql(sql), "#{name} Count").to_i
112
+ end
103
113
  end
104
114
 
105
115
  # Same as <tt>#count_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
106
116
  def async_count_by_sql(sql)
107
- connection.select_value(sanitize_sql(sql), "#{name} Count", async: true).then(&:to_i)
117
+ with_connection do |c|
118
+ c.select_value(sanitize_sql(sql), "#{name} Count", async: true).then(&:to_i)
119
+ end
108
120
  end
109
121
  end
110
122
  end
@@ -31,7 +31,6 @@ module ActiveRecord
31
31
  config.active_record.check_schema_cache_dump_version = true
32
32
  config.active_record.maintain_test_schema = true
33
33
  config.active_record.has_many_inversing = false
34
- config.active_record.sqlite3_production_warning = true
35
34
  config.active_record.query_log_tags_enabled = false
36
35
  config.active_record.query_log_tags = [ :application ]
37
36
  config.active_record.query_log_tags_format = :legacy
@@ -70,6 +69,7 @@ module ActiveRecord
70
69
  Rails.logger.broadcast_to(console)
71
70
  end
72
71
  ActiveRecord.verbose_query_logs = false
72
+ ActiveRecord::Base.attributes_for_inspect = :all
73
73
  end
74
74
 
75
75
  runner do
@@ -88,7 +88,9 @@ module ActiveRecord
88
88
 
89
89
  initializer "active_record.postgresql_time_zone_aware_types" do
90
90
  ActiveSupport.on_load(:active_record_postgresqladapter) do
91
- ActiveRecord::Base.time_zone_aware_types << :timestamptz
91
+ ActiveSupport.on_load(:active_record) do
92
+ ActiveRecord::Base.time_zone_aware_types << :timestamptz
93
+ end
92
94
  end
93
95
  end
94
96
 
@@ -133,48 +135,11 @@ To keep using the current cache store, you can turn off cache versioning entirel
133
135
  end
134
136
  end
135
137
 
136
- initializer "active_record.use_schema_cache_dump" do
137
- ActiveRecord::ConnectionAdapters::SchemaReflection.use_schema_cache_dump = config.active_record.use_schema_cache_dump
138
- end
139
-
140
- initializer "active_record.check_schema_cache_dump" do
141
- check_schema_cache_dump_version = config.active_record.check_schema_cache_dump_version
142
-
143
- ActiveRecord::ConnectionAdapters::SchemaReflection.check_schema_cache_dump_version = check_schema_cache_dump_version
144
-
145
- if config.active_record.use_schema_cache_dump && !config.active_record.lazily_load_schema_cache
146
- config.after_initialize do |app|
147
- ActiveSupport.on_load(:active_record) do
148
- db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
149
-
150
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
151
- db_config.name,
152
- schema_cache_path: db_config.schema_cache_path
153
- )
138
+ initializer "active_record.copy_schema_cache_config" do
139
+ active_record_config = config.active_record
154
140
 
155
- cache = ActiveRecord::ConnectionAdapters::SchemaCache._load_from(filename)
156
- next if cache.nil?
157
-
158
- if check_schema_cache_dump_version
159
- current_version = begin
160
- ActiveRecord::Migrator.current_version
161
- rescue ActiveRecordError => error
162
- warn "Failed to validate the schema cache because of #{error.class}: #{error.message}"
163
- nil
164
- end
165
- next if current_version.nil?
166
-
167
- if cache.schema_version != current_version
168
- warn "Ignoring #{filename} because it has expired. The current schema version is #{current_version}, but the one in the schema cache file is #{cache.schema_version}."
169
- next
170
- end
171
- end
172
-
173
- Rails.logger.info("Using schema cache file #{filename}")
174
- connection_pool.schema_reflection.set_schema_cache(cache)
175
- end
176
- end
177
- end
141
+ ActiveRecord::ConnectionAdapters::SchemaReflection.use_schema_cache_dump = active_record_config.use_schema_cache_dump
142
+ ActiveRecord::ConnectionAdapters::SchemaReflection.check_schema_cache_dump_version = active_record_config.check_schema_cache_dump_version
178
143
  end
179
144
 
180
145
  initializer "active_record.define_attribute_methods" do |app|
@@ -197,7 +162,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
197
162
  # Additionally if `check_schema_cache_dump_version` is enabled (which is the default),
198
163
  # loading the schema cache dump trigger a database connection to compare the schema
199
164
  # versions.
200
- # This means the attribute methods will be lazily defined whent the model is accessed,
165
+ # This means the attribute methods will be lazily defined when the model is accessed,
201
166
  # likely as part of the first few requests or jobs. This isn't good for performance
202
167
  # but we unfortunately have to arbitrate between resiliency and performance, and chose
203
168
  # resiliency.
@@ -221,19 +186,25 @@ To keep using the current cache store, you can turn off cache versioning entirel
221
186
 
222
187
  initializer "active_record.warn_on_records_fetched_greater_than" do
223
188
  if config.active_record.warn_on_records_fetched_greater_than
189
+ ActiveRecord.deprecator.warn <<~MSG.squish
190
+ `config.active_record.warn_on_records_fetched_greater_than` is deprecated and will be
191
+ removed in Rails 8.0.
192
+ Please subscribe to `sql.active_record` notifications and access the row count field to
193
+ detect large result set sizes.
194
+ MSG
224
195
  ActiveSupport.on_load(:active_record) do
225
196
  require "active_record/relation/record_fetch_warning"
226
197
  end
227
198
  end
228
199
  end
229
200
 
230
- SQLITE3_PRODUCTION_WARN = "You are running SQLite in production, this is generally not recommended."\
231
- " You can disable this warning by setting \"config.active_record.sqlite3_production_warning=false\"."
232
- initializer "active_record.sqlite3_production_warning" do
233
- if config.active_record.sqlite3_production_warning && Rails.env.production?
234
- ActiveSupport.on_load(:active_record_sqlite3adapter) do
235
- Rails.logger.warn(SQLITE3_PRODUCTION_WARN)
236
- end
201
+ initializer "active_record.sqlite3_deprecated_warning" do
202
+ if config.active_record.key?(:sqlite3_production_warning)
203
+ config.active_record.delete(:sqlite3_production_warning)
204
+ ActiveRecord.deprecator.warn <<~MSG.squish
205
+ The `config.active_record.sqlite3_production_warning` configuration no longer has any effect
206
+ and can be safely removed.
207
+ MSG
237
208
  end
238
209
  end
239
210
 
@@ -247,6 +218,16 @@ To keep using the current cache store, you can turn off cache versioning entirel
247
218
  end
248
219
  end
249
220
 
221
+ initializer "active_record.postgresql_adapter_decode_dates" do
222
+ config.after_initialize do
223
+ if config.active_record.postgresql_adapter_decode_dates
224
+ ActiveSupport.on_load(:active_record_postgresqladapter) do
225
+ self.decode_dates = true
226
+ end
227
+ end
228
+ end
229
+ end
230
+
250
231
  initializer "active_record.set_configs" do |app|
251
232
  configs = app.config.active_record
252
233
 
@@ -261,8 +242,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
261
242
  end
262
243
 
263
244
  ActiveSupport.on_load(:active_record) do
264
- # Configs used in other initializers
265
- configs = configs.except(
245
+ configs_used_in_other_initializers = configs.except(
266
246
  :migration_error,
267
247
  :database_selector,
268
248
  :database_resolver,
@@ -273,13 +253,13 @@ To keep using the current cache store, you can turn off cache versioning entirel
273
253
  :query_log_tags,
274
254
  :query_log_tags_format,
275
255
  :cache_query_log_tags,
276
- :sqlite3_production_warning,
277
256
  :sqlite3_adapter_strict_strings_by_default,
278
257
  :check_schema_cache_dump_version,
279
- :use_schema_cache_dump
258
+ :use_schema_cache_dump,
259
+ :postgresql_adapter_decode_dates,
280
260
  )
281
261
 
282
- configs.each do |k, v|
262
+ configs_used_in_other_initializers.each do |k, v|
283
263
  next if k == :encryption
284
264
  setter = "#{k}="
285
265
  # Some existing initializers might rely on Active Record configuration
@@ -332,6 +312,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
332
312
  initializer "active_record.set_executor_hooks" do
333
313
  ActiveRecord::QueryCache.install_executor_hooks
334
314
  ActiveRecord::AsynchronousQueriesTracker.install_executor_hooks
315
+ ActiveRecord::ConnectionAdapters::ConnectionPool.install_executor_hooks
335
316
  end
336
317
 
337
318
  initializer "active_record.add_watchable_files" do |app|
@@ -377,23 +358,23 @@ To keep using the current cache store, you can turn off cache versioning entirel
377
358
  end
378
359
 
379
360
  initializer "active_record_encryption.configuration" do |app|
380
- auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
381
-
382
- config.after_initialize do |app|
383
- ActiveRecord::Encryption.configure \
361
+ ActiveSupport.on_load(:active_record_encryption) do
362
+ ActiveRecord::Encryption.configure(
384
363
  primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
385
364
  deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
386
365
  key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
387
- **config.active_record.encryption
366
+ **app.config.active_record.encryption
367
+ )
388
368
 
369
+ auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
389
370
  auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
371
+ end
390
372
 
391
- ActiveSupport.on_load(:active_record) do
392
- # Support extended queries for deterministic attributes and validations
393
- if ActiveRecord::Encryption.config.extend_queries
394
- ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
395
- ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
396
- end
373
+ ActiveSupport.on_load(:active_record) do
374
+ # Support extended queries for deterministic attributes and validations
375
+ if ActiveRecord::Encryption.config.extend_queries
376
+ ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
377
+ ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
397
378
  end
398
379
  end
399
380
 
@@ -414,7 +395,8 @@ To keep using the current cache store, you can turn off cache versioning entirel
414
395
  pid: -> { Process.pid.to_s },
415
396
  socket: ->(context) { context[:connection].pool.db_config.socket },
416
397
  db_host: ->(context) { context[:connection].pool.db_config.host },
417
- database: ->(context) { context[:connection].pool.db_config.database }
398
+ database: ->(context) { context[:connection].pool.db_config.database },
399
+ source_location: -> { QueryLogs.query_source_location }
418
400
  )
419
401
  ActiveRecord.disable_prepared_statements = true
420
402
 
@@ -11,7 +11,14 @@ module ActiveRecord
11
11
  module ClassMethods # :nodoc:
12
12
  def log_process_action(payload)
13
13
  messages, db_runtime = super, payload[:db_runtime]
14
- messages << ("ActiveRecord: %.1fms" % db_runtime.to_f) if db_runtime
14
+
15
+ if db_runtime
16
+ queries_count = payload[:queries_count] || 0
17
+ cached_queries_count = payload[:cached_queries_count] || 0
18
+ messages << ("ActiveRecord: %.1fms (%d %s, %d cached)" % [db_runtime.to_f, queries_count,
19
+ "query".pluralize(queries_count), cached_queries_count])
20
+ end
21
+
15
22
  messages
16
23
  end
17
24
  end
@@ -34,11 +41,11 @@ module ActiveRecord
34
41
 
35
42
  def cleanup_view_runtime
36
43
  if logger && logger.info?
37
- db_rt_before_render = ActiveRecord::RuntimeRegistry.reset
44
+ db_rt_before_render = ActiveRecord::RuntimeRegistry.reset_runtimes
38
45
  self.db_runtime = (db_runtime || 0) + db_rt_before_render
39
46
  runtime = super
40
47
  queries_rt = ActiveRecord::RuntimeRegistry.sql_runtime - ActiveRecord::RuntimeRegistry.async_sql_runtime
41
- db_rt_after_render = ActiveRecord::RuntimeRegistry.reset
48
+ db_rt_after_render = ActiveRecord::RuntimeRegistry.reset_runtimes
42
49
  self.db_runtime += db_rt_after_render
43
50
  runtime - queries_rt
44
51
  else
@@ -49,7 +56,9 @@ module ActiveRecord
49
56
  def append_info_to_payload(payload)
50
57
  super
51
58
 
52
- payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::RuntimeRegistry.reset
59
+ payload[:db_runtime] = (db_runtime || 0) + ActiveRecord::RuntimeRegistry.reset_runtimes
60
+ payload[:queries_count] = ActiveRecord::RuntimeRegistry.reset_queries_count
61
+ payload[:cached_queries_count] = ActiveRecord::RuntimeRegistry.reset_cached_queries_count
53
62
  end
54
63
  end
55
64
  end
@@ -9,10 +9,10 @@ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
9
9
  db_namespace = namespace :db do
10
10
  desc "Set the environment value for the database"
11
11
  task "environment:set" => :load_config do
12
- connection = ActiveRecord::Tasks::DatabaseTasks.migration_connection
13
- raise ActiveRecord::EnvironmentStorageError unless connection.internal_metadata.enabled?
12
+ pool = ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool
13
+ raise ActiveRecord::EnvironmentStorageError unless pool.internal_metadata.enabled?
14
14
 
15
- connection.internal_metadata.create_table_and_set_flags(connection.migration_context.current_environment)
15
+ pool.internal_metadata.create_table_and_set_flags(pool.migration_context.current_environment)
16
16
  end
17
17
 
18
18
  task check_protected_environments: :load_config do
@@ -89,10 +89,10 @@ db_namespace = namespace :db do
89
89
  task migrate: :load_config do
90
90
  db_configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
91
91
 
92
- if db_configs.size == 1
92
+ if db_configs.size == 1 && db_configs.first.primary?
93
93
  ActiveRecord::Tasks::DatabaseTasks.migrate
94
94
  else
95
- mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions(db_configs)
95
+ mapped_versions = ActiveRecord::Tasks::DatabaseTasks.db_configs_with_versions
96
96
 
97
97
  mapped_versions.sort.each do |version, db_configs|
98
98
  db_configs.each do |db_config|
@@ -135,7 +135,7 @@ db_namespace = namespace :db do
135
135
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
136
136
  desc "Migrate #{name} database for current environment"
137
137
  task name => :load_config do
138
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
138
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do
139
139
  ActiveRecord::Tasks::DatabaseTasks.migrate
140
140
  end
141
141
 
@@ -186,7 +186,7 @@ db_namespace = namespace :db do
186
186
 
187
187
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
188
188
 
189
- ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.run(
189
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.run(
190
190
  :up,
191
191
  ActiveRecord::Tasks::DatabaseTasks.target_version
192
192
  )
@@ -199,9 +199,9 @@ db_namespace = namespace :db do
199
199
  task name => :load_config do
200
200
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
201
201
 
202
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
202
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
203
203
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
204
- conn.migration_context.run(:up, ActiveRecord::Tasks::DatabaseTasks.target_version)
204
+ pool.migration_context.run(:up, ActiveRecord::Tasks::DatabaseTasks.target_version)
205
205
  end
206
206
 
207
207
  db_namespace["_dump:#{name}"].invoke
@@ -217,7 +217,7 @@ db_namespace = namespace :db do
217
217
 
218
218
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
219
219
 
220
- ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.run(
220
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.run(
221
221
  :down,
222
222
  ActiveRecord::Tasks::DatabaseTasks.target_version
223
223
  )
@@ -230,9 +230,9 @@ db_namespace = namespace :db do
230
230
  task name => :load_config do
231
231
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
232
232
 
233
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
233
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
234
234
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
235
- conn.migration_context.run(:down, ActiveRecord::Tasks::DatabaseTasks.target_version)
235
+ pool.migration_context.run(:down, ActiveRecord::Tasks::DatabaseTasks.target_version)
236
236
  end
237
237
 
238
238
  db_namespace["_dump:#{name}"].invoke
@@ -242,7 +242,7 @@ db_namespace = namespace :db do
242
242
 
243
243
  desc "Display status of migrations"
244
244
  task status: :load_config do
245
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do
245
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do
246
246
  ActiveRecord::Tasks::DatabaseTasks.migrate_status
247
247
  end
248
248
  end
@@ -251,7 +251,7 @@ db_namespace = namespace :db do
251
251
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
252
252
  desc "Display status of migrations for #{name} database"
253
253
  task name => :load_config do
254
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do
254
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do
255
255
  ActiveRecord::Tasks::DatabaseTasks.migrate_status
256
256
  end
257
257
  end
@@ -265,8 +265,8 @@ db_namespace = namespace :db do
265
265
  task name => :load_config do
266
266
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
267
267
 
268
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
269
- conn.migration_context.rollback(step)
268
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
269
+ pool.migration_context.rollback(step)
270
270
  end
271
271
 
272
272
  db_namespace["_dump:#{name}"].invoke
@@ -281,7 +281,7 @@ db_namespace = namespace :db do
281
281
 
282
282
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
283
283
 
284
- ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.rollback(step)
284
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.rollback(step)
285
285
 
286
286
  db_namespace["_dump"].invoke
287
287
  end
@@ -290,7 +290,7 @@ db_namespace = namespace :db do
290
290
  task forward: :load_config do
291
291
  step = ENV["STEP"] ? ENV["STEP"].to_i : 1
292
292
 
293
- ActiveRecord::Tasks::DatabaseTasks.migration_connection.migration_context.forward(step)
293
+ ActiveRecord::Tasks::DatabaseTasks.migration_connection_pool.migration_context.forward(step)
294
294
 
295
295
  db_namespace["_dump"].invoke
296
296
  end
@@ -321,9 +321,9 @@ db_namespace = namespace :db do
321
321
 
322
322
  desc "Retrieve the current schema version number"
323
323
  task version: :load_config do
324
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env) do |connection|
325
- puts "\ndatabase: #{connection.pool.db_config.database}\n"
326
- puts "Current version: #{connection.schema_version}"
324
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env) do |pool|
325
+ puts "\ndatabase: #{pool.db_config.database}\n"
326
+ puts "Current version: #{pool.migration_context.current_version}"
327
327
  puts
328
328
  end
329
329
  end
@@ -344,8 +344,8 @@ db_namespace = namespace :db do
344
344
  task abort_if_pending_migrations: :load_config do
345
345
  pending_migrations = []
346
346
 
347
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do |conn|
348
- pending_migrations << conn.migration_context.open.pending_migrations
347
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do |pool|
348
+ pending_migrations << pool.migration_context.open.pending_migrations
349
349
  end
350
350
 
351
351
  pending_migrations = pending_migrations.flatten!
@@ -365,8 +365,8 @@ db_namespace = namespace :db do
365
365
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
366
366
  # desc "Raise an error if there are pending migrations for #{name} database"
367
367
  task name => :load_config do
368
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: Rails.env, name: name) do |conn|
369
- pending_migrations = conn.migration_context.open.pending_migrations
368
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: Rails.env, name: name) do |pool|
369
+ pending_migrations = pool.migration_context.open.pending_migrations
370
370
 
371
371
  if pending_migrations.any?
372
372
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
@@ -462,8 +462,8 @@ db_namespace = namespace :db do
462
462
  namespace :schema do
463
463
  desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
464
464
  task dump: :load_config do
465
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do |conn|
466
- db_config = conn.pool.db_config
465
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do |pool|
466
+ db_config = pool.db_config
467
467
  schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
468
468
  ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
469
469
  end
@@ -480,8 +480,8 @@ db_namespace = namespace :db do
480
480
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
481
481
  desc "Create a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) for #{name} database"
482
482
  task name => :load_config do
483
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(name: name) do |conn|
484
- db_config = conn.pool.db_config
483
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
484
+ db_config = pool.db_config
485
485
  schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
486
486
  ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
487
487
  end
@@ -495,8 +495,8 @@ db_namespace = namespace :db do
495
495
  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
496
496
  desc "Load a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the #{name} database"
497
497
  task name => "db:test:purge:#{name}" do
498
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(name: name) do |conn|
499
- db_config = conn.pool.db_config
498
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(name: name) do |pool|
499
+ db_config = pool.db_config
500
500
  schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
501
501
  ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
502
502
  end
@@ -507,21 +507,18 @@ db_namespace = namespace :db do
507
507
  namespace :cache do
508
508
  desc "Create a db/schema_cache.yml file."
509
509
  task dump: :load_config do
510
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each do |conn|
511
- db_config = conn.pool.db_config
512
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.name, schema_cache_path: db_config.schema_cache_path)
510
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each do |pool|
511
+ db_config = pool.db_config
512
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config)
513
513
 
514
- ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
514
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(pool, filename)
515
515
  end
516
516
  end
517
517
 
518
518
  desc "Clear a db/schema_cache.yml file."
519
519
  task clear: :load_config do
520
520
  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
521
- filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
522
- db_config.name,
523
- schema_cache_path: db_config.schema_cache_path,
524
- )
521
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config)
525
522
  ActiveRecord::Tasks::DatabaseTasks.clear_schema_cache(
526
523
  filename,
527
524
  )
@@ -547,8 +544,8 @@ db_namespace = namespace :db do
547
544
  namespace :test do
548
545
  # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
549
546
  task load_schema: %w(db:test:purge) do
550
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: "test") do |conn|
551
- db_config = conn.pool.db_config
547
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test") do |pool|
548
+ db_config = pool.db_config
552
549
  ActiveRecord::Schema.verbose = false
553
550
  schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
554
551
  ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
@@ -573,8 +570,8 @@ db_namespace = namespace :db do
573
570
  # desc "Recreate the #{name} test database from an existent schema.rb file"
574
571
  namespace :load_schema do
575
572
  task name => "db:test:purge:#{name}" do
576
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: "test", name: name) do |conn|
577
- db_config = conn.pool.db_config
573
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test", name: name) do |pool|
574
+ db_config = pool.db_config
578
575
  ActiveRecord::Schema.verbose = false
579
576
  schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
580
577
  ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
@@ -585,8 +582,8 @@ db_namespace = namespace :db do
585
582
  # desc "Empty the #{name} test database"
586
583
  namespace :purge do
587
584
  task name => %w(load_config check_protected_environments) do
588
- ActiveRecord::Tasks::DatabaseTasks.with_temporary_connection_for_each(env: "test", name: name) do |conn|
589
- db_config = conn.pool.db_config
585
+ ActiveRecord::Tasks::DatabaseTasks.with_temporary_pool_for_each(env: "test", name: name) do |pool|
586
+ db_config = pool.db_config
590
587
  ActiveRecord::Tasks::DatabaseTasks.purge(db_config)
591
588
  end
592
589
  end