activerecord 7.1.3.3 → 7.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +251 -0
  3. data/lib/active_record/associations/belongs_to_association.rb +4 -4
  4. data/lib/active_record/associations/collection_association.rb +4 -4
  5. data/lib/active_record/associations/has_many_association.rb +2 -2
  6. data/lib/active_record/associations/has_one_association.rb +2 -2
  7. data/lib/active_record/associations/join_dependency.rb +6 -8
  8. data/lib/active_record/associations.rb +6 -0
  9. data/lib/active_record/attribute_methods/dirty.rb +2 -2
  10. data/lib/active_record/attribute_methods/read.rb +3 -3
  11. data/lib/active_record/attribute_methods/write.rb +3 -3
  12. data/lib/active_record/attribute_methods.rb +46 -6
  13. data/lib/active_record/autosave_association.rb +5 -2
  14. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +8 -1
  15. data/lib/active_record/connection_adapters/abstract/database_statements.rb +1 -1
  16. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  17. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -4
  18. data/lib/active_record/connection_adapters/abstract_adapter.rb +14 -15
  19. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +37 -13
  20. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +2 -1
  21. data/lib/active_record/connection_adapters/mysql2_adapter.rb +16 -10
  22. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  23. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +1 -1
  24. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -2
  25. data/lib/active_record/connection_adapters/trilogy_adapter.rb +16 -20
  26. data/lib/active_record/core.rb +7 -2
  27. data/lib/active_record/counter_cache.rb +7 -3
  28. data/lib/active_record/database_configurations/hash_config.rb +6 -2
  29. data/lib/active_record/delegated_type.rb +6 -6
  30. data/lib/active_record/destroy_association_async_job.rb +1 -1
  31. data/lib/active_record/encryption/encrypted_attribute_type.rb +2 -2
  32. data/lib/active_record/encryption/scheme.rb +8 -4
  33. data/lib/active_record/future_result.rb +9 -0
  34. data/lib/active_record/gem_version.rb +2 -2
  35. data/lib/active_record/locking/optimistic.rb +1 -1
  36. data/lib/active_record/marshalling.rb +1 -1
  37. data/lib/active_record/message_pack.rb +1 -1
  38. data/lib/active_record/migration/compatibility.rb +6 -0
  39. data/lib/active_record/model_schema.rb +6 -2
  40. data/lib/active_record/persistence.rb +2 -2
  41. data/lib/active_record/query_cache.rb +1 -1
  42. data/lib/active_record/query_logs_formatter.rb +1 -1
  43. data/lib/active_record/railtie.rb +10 -13
  44. data/lib/active_record/railties/databases.rake +2 -2
  45. data/lib/active_record/reflection.rb +8 -2
  46. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +6 -1
  47. data/lib/active_record/relation/query_methods.rb +21 -7
  48. data/lib/active_record/relation.rb +13 -3
  49. data/lib/active_record/result.rb +1 -1
  50. data/lib/active_record/tasks/database_tasks.rb +19 -8
  51. data/lib/active_record/test_fixtures.rb +1 -0
  52. data/lib/active_record/timestamp.rb +3 -1
  53. data/lib/active_record.rb +2 -2
  54. data/lib/arel/tree_manager.rb +5 -1
  55. data/lib/arel/visitors/to_sql.rb +2 -1
  56. metadata +10 -10
@@ -336,7 +336,7 @@ module ActiveRecord
336
336
  schema_cache.clear_data_source_cache!(table_name.to_s)
337
337
  schema_cache.clear_data_source_cache!(new_name.to_s)
338
338
  execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}"
339
- rename_table_indexes(table_name, new_name)
339
+ rename_table_indexes(table_name, new_name, **options)
340
340
  end
341
341
 
342
342
  # Drops a table from the database.
@@ -635,18 +635,38 @@ module ActiveRecord
635
635
  end
636
636
 
637
637
  def build_insert_sql(insert) # :nodoc:
638
- sql = +"INSERT #{insert.into} #{insert.values_list}"
639
-
640
- if insert.skip_duplicates?
641
- no_op_column = quote_column_name(insert.keys.first)
642
- sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{no_op_column}"
643
- elsif insert.update_duplicates?
644
- sql << " ON DUPLICATE KEY UPDATE "
645
- if insert.raw_update_sql?
646
- sql << insert.raw_update_sql
647
- else
648
- sql << insert.touch_model_timestamps_unless { |column| "#{column}<=>VALUES(#{column})" }
649
- sql << insert.updatable_columns.map { |column| "#{column}=VALUES(#{column})" }.join(",")
638
+ no_op_column = quote_column_name(insert.keys.first)
639
+
640
+ # MySQL 8.0.19 replaces `VALUES(<expression>)` clauses with row and column alias names, see https://dev.mysql.com/worklog/task/?id=6312 .
641
+ # then MySQL 8.0.20 deprecates the `VALUES(<expression>)` see https://dev.mysql.com/worklog/task/?id=13325 .
642
+ if supports_insert_raw_alias_syntax?
643
+ values_alias = quote_table_name("#{insert.model.table_name}_values")
644
+ sql = +"INSERT #{insert.into} #{insert.values_list} AS #{values_alias}"
645
+
646
+ if insert.skip_duplicates?
647
+ sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{values_alias}.#{no_op_column}"
648
+ elsif insert.update_duplicates?
649
+ if insert.raw_update_sql?
650
+ sql = +"INSERT #{insert.into} #{insert.values_list} ON DUPLICATE KEY UPDATE #{insert.raw_update_sql}"
651
+ else
652
+ sql << " ON DUPLICATE KEY UPDATE "
653
+ sql << insert.touch_model_timestamps_unless { |column| "#{insert.model.quoted_table_name}.#{column}<=>#{values_alias}.#{column}" }
654
+ sql << insert.updatable_columns.map { |column| "#{column}=#{values_alias}.#{column}" }.join(",")
655
+ end
656
+ end
657
+ else
658
+ sql = +"INSERT #{insert.into} #{insert.values_list}"
659
+
660
+ if insert.skip_duplicates?
661
+ sql << " ON DUPLICATE KEY UPDATE #{no_op_column}=#{no_op_column}"
662
+ elsif insert.update_duplicates?
663
+ sql << " ON DUPLICATE KEY UPDATE "
664
+ if insert.raw_update_sql?
665
+ sql << insert.raw_update_sql
666
+ else
667
+ sql << insert.touch_model_timestamps_unless { |column| "#{column}<=>VALUES(#{column})" }
668
+ sql << insert.updatable_columns.map { |column| "#{column}=VALUES(#{column})" }.join(",")
669
+ end
650
670
  end
651
671
  end
652
672
 
@@ -853,6 +873,10 @@ module ActiveRecord
853
873
  "DROP INDEX #{quote_column_name(index_name)}"
854
874
  end
855
875
 
876
+ def supports_insert_raw_alias_syntax?
877
+ !mariadb? && database_version >= "8.0.19"
878
+ end
879
+
856
880
  def supports_rename_index?
857
881
  if mariadb?
858
882
  database_version >= "10.5.2"
@@ -155,7 +155,7 @@ module ActiveRecord
155
155
  end
156
156
 
157
157
  def valid_primary_key_options
158
- super + [:unsigned]
158
+ super + [:unsigned, :auto_increment]
159
159
  end
160
160
 
161
161
  def create_table_definition(name, **options)
@@ -185,6 +185,7 @@ module ActiveRecord
185
185
  default, default_function = nil, default
186
186
  elsif type_metadata.extra == "DEFAULT_GENERATED"
187
187
  default = +"(#{default})" unless default.start_with?("(")
188
+ default = default.gsub("\\'", "'")
188
189
  default, default_function = nil, default
189
190
  elsif type_metadata.type == :text && default&.start_with?("'")
190
191
  # strip and unescape quotes
@@ -131,7 +131,7 @@ module ActiveRecord
131
131
  #++
132
132
 
133
133
  def active?
134
- !!@raw_connection&.ping
134
+ !(@raw_connection.nil? || @raw_connection.closed?) && @lock.synchronize { @raw_connection&.ping } || false
135
135
  end
136
136
 
137
137
  alias :reset! :reconnect!
@@ -139,15 +139,19 @@ module ActiveRecord
139
139
  # Disconnects from the database if already connected.
140
140
  # Otherwise, this method does nothing.
141
141
  def disconnect!
142
- super
143
- @raw_connection&.close
144
- @raw_connection = nil
142
+ @lock.synchronize do
143
+ super
144
+ @raw_connection&.close
145
+ @raw_connection = nil
146
+ end
145
147
  end
146
148
 
147
149
  def discard! # :nodoc:
148
- super
149
- @raw_connection&.automatic_close = false
150
- @raw_connection = nil
150
+ @lock.synchronize do
151
+ super
152
+ @raw_connection&.automatic_close = false
153
+ @raw_connection = nil
154
+ end
151
155
  end
152
156
 
153
157
  private
@@ -162,9 +166,11 @@ module ActiveRecord
162
166
  end
163
167
 
164
168
  def reconnect
165
- @raw_connection&.close
166
- @raw_connection = nil
167
- connect
169
+ @lock.synchronize do
170
+ @raw_connection&.close
171
+ @raw_connection = nil
172
+ connect
173
+ end
168
174
  end
169
175
 
170
176
  def configure_connection
@@ -28,6 +28,12 @@ module ActiveRecord
28
28
  end
29
29
  end
30
30
 
31
+ # TODO: Remove when IPAddr#== compares IPAddr#prefix. See
32
+ # https://github.com/ruby/ipaddr/issues/21
33
+ def changed?(old_value, new_value, _new_value_before_type_cast)
34
+ super || !old_value.nil? && old_value.prefix != new_value.prefix
35
+ end
36
+
31
37
  def cast_value(value)
32
38
  if value.nil?
33
39
  nil
@@ -400,7 +400,7 @@ module ActiveRecord
400
400
  execute "ALTER TABLE #{seq.quoted} RENAME TO #{quote_table_name(new_seq)}"
401
401
  end
402
402
  end
403
- rename_table_indexes(table_name, new_name)
403
+ rename_table_indexes(table_name, new_name, **options)
404
404
  end
405
405
 
406
406
  def add_column(table_name, column_name, type, **options) # :nodoc:
@@ -11,7 +11,7 @@ require "active_record/connection_adapters/sqlite3/schema_definitions"
11
11
  require "active_record/connection_adapters/sqlite3/schema_dumper"
12
12
  require "active_record/connection_adapters/sqlite3/schema_statements"
13
13
 
14
- gem "sqlite3", "~> 1.4"
14
+ gem "sqlite3", ">= 1.4"
15
15
  require "sqlite3"
16
16
 
17
17
  module ActiveRecord
@@ -286,7 +286,7 @@ module ActiveRecord
286
286
  schema_cache.clear_data_source_cache!(table_name.to_s)
287
287
  schema_cache.clear_data_source_cache!(new_name.to_s)
288
288
  exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}"
289
- rename_table_indexes(table_name, new_name)
289
+ rename_table_indexes(table_name, new_name, **options)
290
290
  end
291
291
 
292
292
  def add_column(table_name, column_name, type, **options) # :nodoc:
@@ -102,6 +102,10 @@ module ActiveRecord
102
102
  def initialize(...)
103
103
  super
104
104
 
105
+ if @config[:prepared_statements]
106
+ raise ArgumentError, "Trilogy currently doesn't support prepared statements. Remove `prepared_statements: true` from your database configuration."
107
+ end
108
+
105
109
  # Trilogy ignore `socket` if `host is set. We want the opposite to allow
106
110
  # configuring UNIX domain sockets via `DATABASE_URL`.
107
111
  @config.delete(:host) if @config[:socket]
@@ -140,7 +144,7 @@ module ActiveRecord
140
144
  end
141
145
 
142
146
  def active?
143
- connection&.ping || false
147
+ !(@raw_connection.nil? || @raw_connection.closed?) && @lock.synchronize { @raw_connection&.ping } || false
144
148
  rescue ::Trilogy::Error
145
149
  false
146
150
  end
@@ -148,18 +152,18 @@ module ActiveRecord
148
152
  alias reset! reconnect!
149
153
 
150
154
  def disconnect!
151
- super
152
- unless connection.nil?
153
- connection.close
154
- self.connection = nil
155
+ @lock.synchronize do
156
+ super
157
+ @raw_connection&.close
158
+ @raw_connection = nil
155
159
  end
156
160
  end
157
161
 
158
162
  def discard!
159
- super
160
- unless connection.nil?
161
- connection.discard!
162
- self.connection = nil
163
+ @lock.synchronize do
164
+ super
165
+ @raw_connection&.discard!
166
+ @raw_connection = nil
163
167
  end
164
168
  end
165
169
 
@@ -189,23 +193,15 @@ module ActiveRecord
189
193
  exception.error_code if exception.respond_to?(:error_code)
190
194
  end
191
195
 
192
- def connection
193
- @raw_connection
194
- end
195
-
196
- def connection=(conn)
197
- @raw_connection = conn
198
- end
199
-
200
196
  def connect
201
- self.connection = self.class.new_client(@config)
197
+ @raw_connection = self.class.new_client(@config)
202
198
  rescue ConnectionNotEstablished => ex
203
199
  raise ex.set_pool(@pool)
204
200
  end
205
201
 
206
202
  def reconnect
207
- connection&.close
208
- self.connection = nil
203
+ @raw_connection&.close
204
+ @raw_connection = nil
209
205
  connect
210
206
  end
211
207
 
@@ -396,8 +396,8 @@ module ActiveRecord
396
396
  @arel_table = nil
397
397
  @predicate_builder = nil
398
398
  @inspection_filter = nil
399
- @filter_attributes = nil
400
- @generated_association_methods = nil
399
+ @filter_attributes ||= nil
400
+ @generated_association_methods ||= nil
401
401
  end
402
402
  end
403
403
 
@@ -701,6 +701,11 @@ module ActiveRecord
701
701
  @strict_loading_mode == :n_plus_one_only
702
702
  end
703
703
 
704
+ # Returns +true+ if the record uses strict_loading with +:all+ mode enabled.
705
+ def strict_loading_all?
706
+ @strict_loading_mode == :all
707
+ end
708
+
704
709
  # Marks this record as read only.
705
710
  #
706
711
  # customer = Customer.first
@@ -65,7 +65,7 @@ module ActiveRecord
65
65
  updates.merge!(touch_updates)
66
66
  end
67
67
 
68
- unscoped.where(primary_key => object.id).update_all(updates) if updates.any?
68
+ unscoped.where(primary_key => [object.id]).update_all(updates) if updates.any?
69
69
 
70
70
  true
71
71
  end
@@ -112,6 +112,7 @@ module ActiveRecord
112
112
  # # `updated_at` = '2016-10-13T09:59:23-05:00'
113
113
  # # WHERE id IN (10, 15)
114
114
  def update_counters(id, counters)
115
+ id = [id] if composite_primary_key? && id.is_a?(Array) && !id[0].is_a?(Array)
115
116
  unscoped.where!(primary_key => id).update_counters(counters)
116
117
  end
117
118
 
@@ -198,8 +199,7 @@ module ActiveRecord
198
199
 
199
200
  if affected_rows > 0
200
201
  each_counter_cached_associations do |association|
201
- foreign_key = association.reflection.foreign_key.to_sym
202
- unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
202
+ unless destroyed_by_association && _foreign_keys_equal?(destroyed_by_association.foreign_key, association.reflection.foreign_key)
203
203
  association.decrement_counters
204
204
  end
205
205
  end
@@ -213,5 +213,9 @@ module ActiveRecord
213
213
  yield association(name.to_sym) if reflection.belongs_to? && reflection.counter_cache_column
214
214
  end
215
215
  end
216
+
217
+ def _foreign_keys_equal?(fkey1, fkey2)
218
+ fkey1 == fkey2 || Array(fkey1).map(&:to_sym) == Array(fkey2).map(&:to_sym)
219
+ end
216
220
  end
217
221
  end
@@ -114,8 +114,12 @@ module ActiveRecord
114
114
  configuration_hash[:schema_cache_path]
115
115
  end
116
116
 
117
- def default_schema_cache_path
118
- "db/schema_cache.yml"
117
+ def default_schema_cache_path(db_dir = "db")
118
+ if primary?
119
+ File.join(db_dir, "schema_cache.yml")
120
+ else
121
+ File.join(db_dir, "#{name}_schema_cache.yml")
122
+ end
119
123
  end
120
124
 
121
125
  def lazy_schema_cache_path
@@ -36,7 +36,7 @@ module ActiveRecord
36
36
  #
37
37
  # Let's look at that entry/message/comment example using delegated types:
38
38
  #
39
- # # Schema: entries[ id, account_id, creator_id, created_at, updated_at, entryable_type, entryable_id ]
39
+ # # Schema: entries[ id, account_id, creator_id, entryable_type, entryable_id, created_at, updated_at ]
40
40
  # class Entry < ApplicationRecord
41
41
  # belongs_to :account
42
42
  # belongs_to :creator
@@ -51,12 +51,12 @@ module ActiveRecord
51
51
  # end
52
52
  # end
53
53
  #
54
- # # Schema: messages[ id, subject, body ]
54
+ # # Schema: messages[ id, subject, body, created_at, updated_at ]
55
55
  # class Message < ApplicationRecord
56
56
  # include Entryable
57
57
  # end
58
58
  #
59
- # # Schema: comments[ id, content ]
59
+ # # Schema: comments[ id, content, created_at, updated_at ]
60
60
  # class Comment < ApplicationRecord
61
61
  # include Entryable
62
62
  # end
@@ -102,14 +102,14 @@ module ActiveRecord
102
102
  # You create a new record that uses delegated typing by creating the delegator and delegatee at the same time,
103
103
  # like so:
104
104
  #
105
- # Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user
105
+ # Entry.create! entryable: Comment.new(content: "Hello!"), creator: Current.user, account: Current.account
106
106
  #
107
107
  # If you need more complicated composition, or you need to perform dependent validation, you should build a factory
108
108
  # method or class to take care of the complicated needs. This could be as simple as:
109
109
  #
110
110
  # class Entry < ApplicationRecord
111
- # def self.create_with_comment(content, creator: Current.user)
112
- # create! entryable: Comment.new(content: content), creator: creator
111
+ # def self.create_with_comment(content, creator: Current.user, account: Current.account)
112
+ # create! entryable: Comment.new(content: content), creator: creator, account: account
113
113
  # end
114
114
  # end
115
115
  #
@@ -19,7 +19,7 @@ module ActiveRecord
19
19
  )
20
20
  association_model = association_class.constantize
21
21
  owner_class = owner_model_name.constantize
22
- owner = owner_class.find_by(owner_class.primary_key.to_sym => owner_id)
22
+ owner = owner_class.find_by(owner_class.primary_key => [owner_id])
23
23
 
24
24
  if !owner_destroyed?(owner, ensuring_owner_was_method)
25
25
  raise DestroyAssociationAsyncError, "owner record not destroyed"
@@ -140,11 +140,11 @@ module ActiveRecord
140
140
  end
141
141
 
142
142
  def encryption_options
143
- @encryption_options ||= { key_provider: key_provider, cipher_options: { deterministic: deterministic? } }.compact
143
+ { key_provider: key_provider, cipher_options: { deterministic: deterministic? } }.compact
144
144
  end
145
145
 
146
146
  def decryption_options
147
- @decryption_options ||= { key_provider: key_provider }.compact
147
+ { key_provider: key_provider }.compact
148
148
  end
149
149
 
150
150
  def clean_text_scheme
@@ -50,7 +50,7 @@ module ActiveRecord
50
50
  end
51
51
 
52
52
  def key_provider
53
- @key_provider ||= @key_provider_param || build_key_provider || default_key_provider
53
+ @key_provider_param || key_provider_from_key || deterministic_key_provider || default_key_provider
54
54
  end
55
55
 
56
56
  def merge(other_scheme)
@@ -80,10 +80,14 @@ module ActiveRecord
80
80
  raise Errors::Configuration, "key_provider: and key: can't be used simultaneously" if @key_provider_param && @key
81
81
  end
82
82
 
83
- def build_key_provider
84
- return DerivedSecretKeyProvider.new(@key) if @key.present?
83
+ def key_provider_from_key
84
+ @key_provider_from_key ||= if @key.present?
85
+ DerivedSecretKeyProvider.new(@key)
86
+ end
87
+ end
85
88
 
86
- if @deterministic
89
+ def deterministic_key_provider
90
+ @deterministic_key_provider ||= if @deterministic
87
91
  DeterministicKeyProvider.new(ActiveRecord::Encryption.config.deterministic_key)
88
92
  end
89
93
  end
@@ -47,6 +47,15 @@ module ActiveRecord
47
47
 
48
48
  Canceled = Class.new(ActiveRecordError)
49
49
 
50
+ def self.wrap(result)
51
+ case result
52
+ when self, Complete
53
+ result
54
+ else
55
+ Complete.new(result)
56
+ end
57
+ end
58
+
50
59
  delegate :empty?, :to_a, to: :result
51
60
  delegate_missing_to :result
52
61
 
@@ -9,8 +9,8 @@ module ActiveRecord
9
9
  module VERSION
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
- TINY = 3
13
- PRE = "3"
12
+ TINY = 4
13
+ PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  # == Usage
15
15
  #
16
16
  # Active Record supports optimistic locking if the +lock_version+ field is present. Each update to the
17
- # record increments the +lock_version+ column and the locking facilities ensure that records instantiated twice
17
+ # record increments the integer column +lock_version+ and the locking facilities ensure that records instantiated twice
18
18
  # will let the last one saved raise a +StaleObjectError+ if the first was also updated. Example:
19
19
  #
20
20
  # p1 = Person.find(1)
@@ -25,7 +25,7 @@ module ActiveRecord
25
25
  payload = [attributes_for_database, new_record?]
26
26
 
27
27
  cached_associations = self.class.reflect_on_all_associations.select do |reflection|
28
- association_cached?(reflection.name)
28
+ association_cached?(reflection.name) && association(reflection.name).loaded?
29
29
  end
30
30
 
31
31
  unless cached_associations.empty?
@@ -80,7 +80,7 @@ module ActiveRecord
80
80
 
81
81
  def add_cached_associations(record, entry)
82
82
  record.class.reflections.each_value do |reflection|
83
- if record.association_cached?(reflection.name)
83
+ if record.association_cached?(reflection.name) && record.association(reflection.name).loaded?
84
84
  entry << reflection.name << encode(record.association(reflection.name).target)
85
85
  end
86
86
  end
@@ -80,6 +80,11 @@ module ActiveRecord
80
80
  super
81
81
  end
82
82
 
83
+ def references(*args, **options)
84
+ options[:_skip_validate_options] = true
85
+ super
86
+ end
87
+
83
88
  private
84
89
  def raise_on_if_exist_options(options)
85
90
  end
@@ -112,6 +117,7 @@ module ActiveRecord
112
117
 
113
118
  def rename_table(table_name, new_name, **options)
114
119
  options[:_uses_legacy_table_name] = true
120
+ options[:_uses_legacy_index_name] = true
115
121
  super
116
122
  end
117
123
 
@@ -432,8 +432,12 @@ module ActiveRecord
432
432
  end
433
433
 
434
434
  def _returning_columns_for_insert # :nodoc:
435
- @_returning_columns_for_insert ||= columns.filter_map do |c|
436
- c.name if connection.return_value_after_insert?(c)
435
+ @_returning_columns_for_insert ||= begin
436
+ auto_populated_columns = columns.filter_map do |c|
437
+ c.name if connection.return_value_after_insert?(c)
438
+ end
439
+
440
+ auto_populated_columns.empty? ? Array(primary_key) : auto_populated_columns
437
441
  end
438
442
  end
439
443
 
@@ -456,7 +456,7 @@ module ActiveRecord
456
456
  end
457
457
 
458
458
  # Accepts a list of attribute names to be used in the WHERE clause
459
- # of SELECT / UPDATE / DELETE queries and in the ORDER BY clause for `#first` and `#last` finder methods.
459
+ # of SELECT / UPDATE / DELETE queries and in the ORDER BY clause for +#first+ and +#last+ finder methods.
460
460
  #
461
461
  # class Developer < ActiveRecord::Base
462
462
  # query_constraints :company_id, :id
@@ -469,7 +469,7 @@ module ActiveRecord
469
469
  # developer.update!(name: "Nikita")
470
470
  # # UPDATE "developers" SET "name" = 'Nikita' WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
471
471
  #
472
- # It is possible to update attribute used in the query_by clause:
472
+ # # It is possible to update an attribute used in the query_constraints clause:
473
473
  # developer.update!(company_id: 2)
474
474
  # # UPDATE "developers" SET "company_id" = 2 WHERE "developers"."company_id" = 1 AND "developers"."id" = 1
475
475
  #
@@ -30,7 +30,7 @@ module ActiveRecord
30
30
  end
31
31
 
32
32
  def self.complete(pools)
33
- pools.each { |pool| pool.disable_query_cache! }
33
+ pools.each { |pool| pool.disable_query_cache! unless pool.discarded? }
34
34
 
35
35
  ActiveRecord::Base.connection_handler.each_connection_pool do |pool|
36
36
  pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
@@ -28,7 +28,7 @@ module ActiveRecord
28
28
  end
29
29
 
30
30
  def format(pairs)
31
- pairs.sort_by!(&:first)
31
+ pairs.sort_by! { |pair| pair.first.to_s }
32
32
  super
33
33
  end
34
34
 
@@ -146,6 +146,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
146
146
  config.after_initialize do |app|
147
147
  ActiveSupport.on_load(:active_record) do
148
148
  db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first
149
+ next if db_config.nil?
149
150
 
150
151
  filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
151
152
  db_config.name,
@@ -261,8 +262,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
261
262
  end
262
263
 
263
264
  ActiveSupport.on_load(:active_record) do
264
- # Configs used in other initializers
265
- configs = configs.except(
265
+ configs_used_in_other_initializers = configs.except(
266
266
  :migration_error,
267
267
  :database_selector,
268
268
  :database_resolver,
@@ -279,7 +279,7 @@ To keep using the current cache store, you can turn off cache versioning entirel
279
279
  :use_schema_cache_dump
280
280
  )
281
281
 
282
- configs.each do |k, v|
282
+ configs_used_in_other_initializers.each do |k, v|
283
283
  next if k == :encryption
284
284
  setter = "#{k}="
285
285
  # Some existing initializers might rely on Active Record configuration
@@ -377,23 +377,20 @@ To keep using the current cache store, you can turn off cache versioning entirel
377
377
  end
378
378
 
379
379
  initializer "active_record_encryption.configuration" do |app|
380
- auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
381
-
382
- config.after_initialize do |app|
380
+ ActiveSupport.on_load(:active_record) do
383
381
  ActiveRecord::Encryption.configure \
384
382
  primary_key: app.credentials.dig(:active_record_encryption, :primary_key),
385
383
  deterministic_key: app.credentials.dig(:active_record_encryption, :deterministic_key),
386
384
  key_derivation_salt: app.credentials.dig(:active_record_encryption, :key_derivation_salt),
387
- **config.active_record.encryption
385
+ **app.config.active_record.encryption
388
386
 
387
+ auto_filtered_parameters = ActiveRecord::Encryption::AutoFilteredParameters.new(app)
389
388
  auto_filtered_parameters.enable if ActiveRecord::Encryption.config.add_to_filter_parameters
390
389
 
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
390
+ # Support extended queries for deterministic attributes and validations
391
+ if ActiveRecord::Encryption.config.extend_queries
392
+ ActiveRecord::Encryption::ExtendedDeterministicQueries.install_support
393
+ ActiveRecord::Encryption::ExtendedDeterministicUniquenessValidator.install_support
397
394
  end
398
395
  end
399
396
 
@@ -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|