activerecord 7.1.0.beta1 → 7.1.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +85 -4
  3. data/lib/active_record/associations/collection_association.rb +1 -3
  4. data/lib/active_record/associations/collection_proxy.rb +1 -1
  5. data/lib/active_record/associations.rb +110 -110
  6. data/lib/active_record/connection_adapters/abstract/database_statements.rb +20 -1
  7. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +3 -3
  8. data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -9
  9. data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -1
  10. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +7 -0
  11. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
  12. data/lib/active_record/connection_adapters/pool_manager.rb +1 -1
  13. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +0 -16
  14. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -5
  15. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -24
  16. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -8
  17. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +25 -29
  18. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -6
  19. data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
  20. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +4 -4
  21. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -4
  22. data/lib/active_record/core.rb +7 -9
  23. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -1
  24. data/lib/active_record/errors.rb +19 -0
  25. data/lib/active_record/gem_version.rb +1 -1
  26. data/lib/active_record/migration/command_recorder.rb +8 -8
  27. data/lib/active_record/nested_attributes.rb +0 -5
  28. data/lib/active_record/normalization.rb +2 -1
  29. data/lib/active_record/persistence.rb +1 -1
  30. data/lib/active_record/querying.rb +2 -2
  31. data/lib/active_record/railtie.rb +1 -1
  32. data/lib/active_record/reflection.rb +10 -16
  33. data/lib/active_record/relation/calculations.rb +8 -8
  34. data/lib/active_record/relation/finder_methods.rb +3 -12
  35. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
  36. data/lib/active_record/schema_dumper.rb +9 -4
  37. data/lib/active_record/tasks/sqlite_database_tasks.rb +1 -0
  38. metadata +9 -9
@@ -126,6 +126,7 @@ module ActiveRecord
126
126
 
127
127
  @config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
128
128
  @connection_parameters = @config.merge(database: @config[:database].to_s, results_as_hash: true)
129
+ @use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
129
130
  end
130
131
 
131
132
  def database_exists?
@@ -180,6 +181,10 @@ module ActiveRecord
180
181
  database_version >= "3.8.3"
181
182
  end
182
183
 
184
+ def supports_insert_returning?
185
+ database_version >= "3.35.0"
186
+ end
187
+
183
188
  def supports_insert_on_conflict?
184
189
  database_version >= "3.24.0"
185
190
  end
@@ -195,6 +200,10 @@ module ActiveRecord
195
200
  @raw_connection && !@raw_connection.closed?
196
201
  end
197
202
 
203
+ def return_value_after_insert?(column) # :nodoc:
204
+ column.auto_populated?
205
+ end
206
+
198
207
  alias :reset! :reconnect!
199
208
 
200
209
  # Disconnects from the database if already connected. Otherwise, this
@@ -393,6 +402,7 @@ module ActiveRecord
393
402
  end
394
403
  end
395
404
 
405
+ sql << " RETURNING #{insert.returning}" if insert.returning
396
406
  sql
397
407
  end
398
408
 
@@ -400,6 +410,10 @@ module ActiveRecord
400
410
  @config.fetch(:flags, 0).anybits?(::SQLite3::Constants::Open::SHAREDCACHE)
401
411
  end
402
412
 
413
+ def use_insert_returning?
414
+ @use_insert_returning
415
+ end
416
+
403
417
  def get_database_version # :nodoc:
404
418
  SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
405
419
  end
@@ -451,10 +465,10 @@ module ActiveRecord
451
465
  when /^null$/i
452
466
  nil
453
467
  # Quoted types
454
- when /^'(.*)'$/m
468
+ when /^'([^|]*)'$/m
455
469
  $1.gsub("''", "'")
456
470
  # Quoted types
457
- when /^"(.*)"$/m
471
+ when /^"([^|]*)"$/m
458
472
  $1.gsub('""', '"')
459
473
  # Numeric types
460
474
  when /\A-?\d+(\.\d*)?\z/
@@ -474,7 +488,7 @@ module ActiveRecord
474
488
  end
475
489
 
476
490
  def has_default_function?(default_value, default)
477
- !default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
491
+ !default_value && %r{\w+\(.*\)|CURRENT_TIME|CURRENT_DATE|CURRENT_TIMESTAMP|\|\|}.match?(default)
478
492
  end
479
493
 
480
494
  # See: https://www.sqlite.org/lang_altertable.html
@@ -698,9 +712,40 @@ module ActiveRecord
698
712
  end
699
713
 
700
714
  def configure_connection
701
- @raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout])) if @config[:timeout]
715
+ if @config[:timeout] && @config[:retries]
716
+ raise ArgumentError, "Cannot specify both timeout and retries arguments"
717
+ elsif @config[:timeout]
718
+ @raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout]))
719
+ elsif @config[:retries]
720
+ retries = self.class.type_cast_config_to_integer(@config[:retries])
721
+ raw_connection.busy_handler do |count|
722
+ count <= retries
723
+ end
724
+ end
702
725
 
726
+ # Enforce foreign key constraints
727
+ # https://www.sqlite.org/pragma.html#pragma_foreign_keys
728
+ # https://www.sqlite.org/foreignkeys.html
703
729
  raw_execute("PRAGMA foreign_keys = ON", "SCHEMA")
730
+ unless @memory_database
731
+ # Journal mode WAL allows for greater concurrency (many readers + one writer)
732
+ # https://www.sqlite.org/pragma.html#pragma_journal_mode
733
+ raw_execute("PRAGMA journal_mode = WAL", "SCHEMA")
734
+ # Set more relaxed level of database durability
735
+ # 2 = "FULL" (sync on every write), 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
736
+ # https://www.sqlite.org/pragma.html#pragma_synchronous
737
+ raw_execute("PRAGMA synchronous = NORMAL", "SCHEMA")
738
+ # Set the global memory map so all processes can share some data
739
+ # https://www.sqlite.org/pragma.html#pragma_mmap_size
740
+ # https://www.sqlite.org/mmap.html
741
+ raw_execute("PRAGMA mmap_size = #{128.megabytes}", "SCHEMA")
742
+ end
743
+ # Impose a limit on the WAL file to prevent unlimited growth
744
+ # https://www.sqlite.org/pragma.html#pragma_journal_size_limit
745
+ raw_execute("PRAGMA journal_size_limit = #{64.megabytes}", "SCHEMA")
746
+ # Set the local connection cache to 2000 pages
747
+ # https://www.sqlite.org/pragma.html#pragma_cache_size
748
+ raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
704
749
  end
705
750
  end
706
751
  ActiveSupport.run_load_hooks(:active_record_sqlite3adapter, SQLite3Adapter)
@@ -344,11 +344,6 @@ module ActiveRecord
344
344
  end
345
345
  end
346
346
 
347
- # Override the default class equality method to provide support for decorated models.
348
- def ===(object) # :nodoc:
349
- object.is_a?(self)
350
- end
351
-
352
347
  # Returns an instance of +Arel::Table+ loaded with the current table name.
353
348
  def arel_table # :nodoc:
354
349
  @arel_table ||= Arel::Table.new(table_name, klass: self)
@@ -615,7 +610,9 @@ module ActiveRecord
615
610
  #
616
611
  # user = User.first
617
612
  # user.strict_loading! # => true
618
- # user.comments
613
+ # user.address.city
614
+ # => ActiveRecord::StrictLoadingViolationError
615
+ # user.comments.to_a
619
616
  # => ActiveRecord::StrictLoadingViolationError
620
617
  #
621
618
  # ==== Parameters
@@ -629,12 +626,13 @@ module ActiveRecord
629
626
  #
630
627
  # user = User.first
631
628
  # user.strict_loading!(false) # => false
632
- # user.comments
633
- # => #<ActiveRecord::Associations::CollectionProxy>
629
+ # user.address.city # => "Tatooine"
630
+ # user.comments.to_a # => [#<Comment:0x00...]
634
631
  #
635
632
  # user.strict_loading!(mode: :n_plus_one_only)
636
633
  # user.address.city # => "Tatooine"
637
- # user.comments
634
+ # user.comments.to_a # => [#<Comment:0x00...]
635
+ # user.comments.first.ratings.to_a
638
636
  # => ActiveRecord::StrictLoadingViolationError
639
637
  def strict_loading!(value = true, mode: :all)
640
638
  unless [:all, :n_plus_one_only].include?(mode)
@@ -14,7 +14,7 @@ module ActiveRecord
14
14
  klass = record.class
15
15
  if klass.deterministic_encrypted_attributes&.include?(attribute)
16
16
  encrypted_type = klass.type_for_attribute(attribute)
17
- [ encrypted_type, *encrypted_type.previous_types ].each do |type|
17
+ encrypted_type.previous_types.each do |type|
18
18
  encrypted_value = type.serialize(value)
19
19
  ActiveRecord::Encryption.without_encryption do
20
20
  super(record, attribute, encrypted_value)
@@ -483,6 +483,19 @@ module ActiveRecord
483
483
  # TransactionRollbackError will be raised when a transaction is rolled
484
484
  # back by the database due to a serialization failure or a deadlock.
485
485
  #
486
+ # These exceptions should not be generally rescued in nested transaction
487
+ # blocks, because they have side-effects in the actual enclosing transaction
488
+ # and internal Active Record state. They can be rescued if you are above the
489
+ # root transaction block, though.
490
+ #
491
+ # In that case, beware of transactional tests, however, because they run test
492
+ # cases in their own umbrella transaction. If you absolutely need to handle
493
+ # these exceptions in tests please consider disabling transactional tests in
494
+ # the affected test class (<tt>self.use_transactional_tests = false</tt>).
495
+ #
496
+ # Due to the aforementioned side-effects, this exception should not be raised
497
+ # manually by users.
498
+ #
486
499
  # See the following:
487
500
  #
488
501
  # * https://www.postgresql.org/docs/current/static/transaction-iso.html
@@ -497,11 +510,17 @@ module ActiveRecord
497
510
 
498
511
  # SerializationFailure will be raised when a transaction is rolled
499
512
  # back by the database due to a serialization failure.
513
+ #
514
+ # This is a subclass of TransactionRollbackError, please make sure to check
515
+ # its documentation to be aware of its caveats.
500
516
  class SerializationFailure < TransactionRollbackError
501
517
  end
502
518
 
503
519
  # Deadlocked will be raised when a transaction is rolled
504
520
  # back by the database when a deadlock is encountered.
521
+ #
522
+ # This is a subclass of TransactionRollbackError, please make sure to check
523
+ # its documentation to be aware of its caveats.
505
524
  class Deadlocked < TransactionRollbackError
506
525
  end
507
526
 
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  MAJOR = 7
11
11
  MINOR = 1
12
12
  TINY = 0
13
- PRE = "beta1"
13
+ PRE = "rc2"
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
16
16
  end
@@ -12,7 +12,7 @@ module ActiveRecord
12
12
  # * add_foreign_key
13
13
  # * add_check_constraint
14
14
  # * add_exclusion_constraint
15
- # * add_unique_key
15
+ # * add_unique_constraint
16
16
  # * add_index
17
17
  # * add_reference
18
18
  # * add_timestamps
@@ -33,7 +33,7 @@ module ActiveRecord
33
33
  # * remove_foreign_key (must supply a second table)
34
34
  # * remove_check_constraint
35
35
  # * remove_exclusion_constraint
36
- # * remove_unique_key
36
+ # * remove_unique_constraint
37
37
  # * remove_index
38
38
  # * remove_reference
39
39
  # * remove_timestamps
@@ -53,7 +53,7 @@ module ActiveRecord
53
53
  :change_column_comment, :change_table_comment,
54
54
  :add_check_constraint, :remove_check_constraint,
55
55
  :add_exclusion_constraint, :remove_exclusion_constraint,
56
- :add_unique_key, :remove_unique_key,
56
+ :add_unique_constraint, :remove_unique_constraint,
57
57
  :create_enum, :drop_enum, :rename_enum, :add_enum_value, :rename_enum_value,
58
58
  ]
59
59
  include JoinTable
@@ -161,7 +161,7 @@ module ActiveRecord
161
161
  add_foreign_key: :remove_foreign_key,
162
162
  add_check_constraint: :remove_check_constraint,
163
163
  add_exclusion_constraint: :remove_exclusion_constraint,
164
- add_unique_key: :remove_unique_key,
164
+ add_unique_constraint: :remove_unique_constraint,
165
165
  enable_extension: :disable_extension,
166
166
  create_enum: :drop_enum
167
167
  }.each do |cmd, inv|
@@ -329,17 +329,17 @@ module ActiveRecord
329
329
  super
330
330
  end
331
331
 
332
- def invert_add_unique_key(args)
332
+ def invert_add_unique_constraint(args)
333
333
  options = args.dup.extract_options!
334
334
 
335
- raise ActiveRecord::IrreversibleMigration, "add_unique_key is not reversible if given an using_index." if options[:using_index]
335
+ raise ActiveRecord::IrreversibleMigration, "add_unique_constraint is not reversible if given an using_index." if options[:using_index]
336
336
  super
337
337
  end
338
338
 
339
- def invert_remove_unique_key(args)
339
+ def invert_remove_unique_constraint(args)
340
340
  _table, columns = args.dup.tap(&:extract_options!)
341
341
 
342
- raise ActiveRecord::IrreversibleMigration, "remove_unique_key is only reversible if given an column_name." if columns.blank?
342
+ raise ActiveRecord::IrreversibleMigration, "remove_unique_constraint is only reversible if given an column_name." if columns.blank?
343
343
  super
344
344
  end
345
345
 
@@ -355,17 +355,12 @@ module ActiveRecord
355
355
  options.update(attr_names.extract_options!)
356
356
  options.assert_valid_keys(:allow_destroy, :reject_if, :limit, :update_only)
357
357
  options[:reject_if] = REJECT_ALL_BLANK_PROC if options[:reject_if] == :all_blank
358
- options[:class] = self
359
358
 
360
359
  attr_names.each do |association_name|
361
360
  if reflection = _reflect_on_association(association_name)
362
361
  reflection.autosave = true
363
362
  define_autosave_validation_callbacks(reflection)
364
363
 
365
- if nested_attributes_options.dig(association_name.to_sym, :class) == self
366
- raise ArgumentError, "Already declared #{association_name} as an accepts_nested_attributes association for this class."
367
- end
368
-
369
364
  nested_attributes_options = self.nested_attributes_options.dup
370
365
  nested_attributes_options[association_name.to_sym] = options
371
366
  self.nested_attributes_options = nested_attributes_options
@@ -51,7 +51,8 @@ module ActiveRecord # :nodoc:
51
51
  #
52
52
  # ==== Options
53
53
  #
54
- # * +:with+ - The normalization to apply.
54
+ # * +:with+ - Any callable object that accepts the attribute's value as
55
+ # its sole argument, and returns it normalized.
55
56
  # * +:apply_to_nil+ - Whether to apply the normalization to +nil+ values.
56
57
  # Defaults to +false+.
57
58
  #
@@ -1272,7 +1272,7 @@ module ActiveRecord
1272
1272
  def _raise_record_not_destroyed
1273
1273
  @_association_destroy_exception ||= nil
1274
1274
  key = self.class.primary_key
1275
- raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{send(key)}", self)
1275
+ raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy #{self.class} with #{key}=#{id}", self)
1276
1276
  ensure
1277
1277
  @_association_destroy_exception = nil
1278
1278
  end
@@ -51,7 +51,7 @@ module ActiveRecord
51
51
  _load_from_sql(_query_by_sql(sql, binds, preparable: preparable), &block)
52
52
  end
53
53
 
54
- # Same as <tt>#find_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
54
+ # Same as <tt>#find_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
55
55
  def async_find_by_sql(sql, binds = [], preparable: nil, &block)
56
56
  _query_by_sql(sql, binds, preparable: preparable, async: true).then do |result|
57
57
  _load_from_sql(result, &block)
@@ -102,7 +102,7 @@ module ActiveRecord
102
102
  connection.select_value(sanitize_sql(sql), "#{name} Count").to_i
103
103
  end
104
104
 
105
- # Same as <tt>#count_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
105
+ # Same as <tt>#count_by_sql</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
106
106
  def async_count_by_sql(sql)
107
107
  connection.select_value(sanitize_sql(sql), "#{name} Count", async: true).then(&:to_i)
108
108
  end
@@ -67,7 +67,7 @@ module ActiveRecord
67
67
  unless ActiveSupport::Logger.logger_outputs_to?(Rails.logger, STDERR, STDOUT)
68
68
  console = ActiveSupport::Logger.new(STDERR)
69
69
  console.level = Rails.logger.level
70
- Rails.logger.extend ActiveSupport::Logger.broadcast console
70
+ Rails.logger.broadcast_to(console)
71
71
  end
72
72
  ActiveRecord.verbose_query_logs = false
73
73
  end
@@ -507,7 +507,7 @@ module ActiveRecord
507
507
  derived_fk = derive_foreign_key(infer_from_inverse_of: infer_from_inverse_of)
508
508
 
509
509
  if active_record.has_query_constraints?
510
- derived_fk = derive_fk_query_constraints(active_record, derived_fk)
510
+ derived_fk = derive_fk_query_constraints(derived_fk)
511
511
  end
512
512
 
513
513
  derived_fk
@@ -770,13 +770,13 @@ module ActiveRecord
770
770
  end
771
771
  end
772
772
 
773
- def derive_fk_query_constraints(klass, foreign_key)
774
- primary_query_constraints = klass.query_constraints_list
775
- owner_pk = klass.primary_key
773
+ def derive_fk_query_constraints(foreign_key)
774
+ primary_query_constraints = active_record.query_constraints_list
775
+ owner_pk = active_record.primary_key
776
776
 
777
777
  if primary_query_constraints.size != 2
778
778
  raise ArgumentError, <<~MSG.squish
779
- The query constraints list on the `#{klass}` model has more than 2
779
+ The query constraints list on the `#{active_record}` model has more than 2
780
780
  attributes. Active Record is unable to derive the query constraints
781
781
  for the association. You need to explicitly define the query constraints
782
782
  for this association.
@@ -785,19 +785,13 @@ module ActiveRecord
785
785
 
786
786
  if !primary_query_constraints.include?(owner_pk)
787
787
  raise ArgumentError, <<~MSG.squish
788
- The query constraints on the `#{klass}` model does not include the primary
788
+ The query constraints on the `#{active_record}` model does not include the primary
789
789
  key so Active Record is unable to derive the foreign key constraints for
790
790
  the association. You need to explicitly define the query constraints for this
791
791
  association.
792
792
  MSG
793
793
  end
794
794
 
795
- # The primary key and foreign key are both already in the query constraints
796
- # so we don't want to derive the key. In this case we want a single key.
797
- if primary_query_constraints.include?(owner_pk) && primary_query_constraints.include?(foreign_key)
798
- return foreign_key
799
- end
800
-
801
795
  first_key, last_key = primary_query_constraints
802
796
 
803
797
  if first_key == owner_pk
@@ -807,7 +801,7 @@ module ActiveRecord
807
801
  else
808
802
  raise ArgumentError, <<~MSG.squish
809
803
  Active Record couldn't correctly interpret the query constraints
810
- for the `#{klass}` model. The query constraints on `#{klass}` are
804
+ for the `#{active_record}` model. The query constraints on `#{active_record}` are
811
805
  `#{primary_query_constraints}` and the foreign key is `#{foreign_key}`.
812
806
  You need to explicitly set the query constraints for this association.
813
807
  MSG
@@ -862,10 +856,10 @@ module ActiveRecord
862
856
 
863
857
  # klass option is necessary to support loading polymorphic associations
864
858
  def association_primary_key(klass = nil)
865
- if !polymorphic? && ((klass || self.klass).has_query_constraints? || options[:query_constraints])
866
- (klass || self.klass).composite_query_constraints_list
867
- elsif primary_key = options[:primary_key]
859
+ if primary_key = options[:primary_key]
868
860
  @association_primary_key ||= -primary_key.to_s
861
+ elsif !polymorphic? && ((klass || self.klass).has_query_constraints? || options[:query_constraints])
862
+ (klass || self.klass).composite_query_constraints_list
869
863
  elsif (klass || self.klass).composite_primary_key?
870
864
  # If klass has composite primary key of shape [:<tenant_key>, :id], infer primary_key as :id
871
865
  primary_key = (klass || self.klass).primary_key
@@ -93,7 +93,7 @@ module ActiveRecord
93
93
  end
94
94
  end
95
95
 
96
- # Same as <tt>#count</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
96
+ # Same as <tt>#count</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
97
97
  def async_count(column_name = nil)
98
98
  async.count(column_name)
99
99
  end
@@ -106,7 +106,7 @@ module ActiveRecord
106
106
  calculate(:average, column_name)
107
107
  end
108
108
 
109
- # Same as <tt>#average</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
109
+ # Same as <tt>#average</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
110
110
  def async_average(column_name)
111
111
  async.average(column_name)
112
112
  end
@@ -120,7 +120,7 @@ module ActiveRecord
120
120
  calculate(:minimum, column_name)
121
121
  end
122
122
 
123
- # Same as <tt>#minimum</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
123
+ # Same as <tt>#minimum</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
124
124
  def async_minimum(column_name)
125
125
  async.minimum(column_name)
126
126
  end
@@ -134,7 +134,7 @@ module ActiveRecord
134
134
  calculate(:maximum, column_name)
135
135
  end
136
136
 
137
- # Same as <tt>#maximum</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
137
+ # Same as <tt>#maximum</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
138
138
  def async_maximum(column_name)
139
139
  async.maximum(column_name)
140
140
  end
@@ -152,7 +152,7 @@ module ActiveRecord
152
152
  end
153
153
  end
154
154
 
155
- # Same as <tt>#sum</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
155
+ # Same as <tt>#sum</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
156
156
  def async_sum(identity_or_column = nil)
157
157
  async.sum(identity_or_column)
158
158
  end
@@ -287,7 +287,7 @@ module ActiveRecord
287
287
  end
288
288
  end
289
289
 
290
- # Same as <tt>#pluck</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
290
+ # Same as <tt>#pluck</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
291
291
  def async_pluck(*column_names)
292
292
  async.pluck(*column_names)
293
293
  end
@@ -315,7 +315,7 @@ module ActiveRecord
315
315
  limit(1).pluck(*column_names).then(&:first)
316
316
  end
317
317
 
318
- # Same as <tt>#pick</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
318
+ # Same as <tt>#pick</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
319
319
  def async_pick(*column_names)
320
320
  async.pick(*column_names)
321
321
  end
@@ -358,7 +358,7 @@ module ActiveRecord
358
358
  result.then { |result| type_cast_pluck_values(result, columns) }
359
359
  end
360
360
 
361
- # Same as <tt>#ids</tt> but perform the query asynchronously and returns an ActiveRecord::Promise
361
+ # Same as <tt>#ids</tt> but perform the query asynchronously and returns an ActiveRecord::Promise.
362
362
  def async_ids
363
363
  async.ids
364
364
  end
@@ -16,7 +16,7 @@ module ActiveRecord
16
16
  # Person.find("1") # returns the object for ID = 1
17
17
  # Person.find("31-sarah") # returns the object for ID = 31
18
18
  # Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6)
19
- # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17)
19
+ # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17), or with composite primary key [7, 17]
20
20
  # Person.find([1]) # returns an array for the object with ID = 1
21
21
  # Person.where("administrator = 1").order("created_on DESC").find(1)
22
22
  #
@@ -527,12 +527,7 @@ module ActiveRecord
527
527
  def find_some(ids)
528
528
  return find_some_ordered(ids) unless order_values.present?
529
529
 
530
- relation = if klass.composite_primary_key?
531
- ids.map { |values_set| where(primary_key.zip(values_set).to_h) }.inject(&:or)
532
- else
533
- where(primary_key => ids)
534
- end
535
-
530
+ relation = where(primary_key => ids)
536
531
  relation = relation.select(table[primary_key]) unless select_values.empty?
537
532
  result = relation.to_a
538
533
 
@@ -559,11 +554,7 @@ module ActiveRecord
559
554
  ids = ids.slice(offset_value || 0, limit_value || ids.size) || []
560
555
 
561
556
  relation = except(:limit, :offset)
562
- relation = if klass.composite_primary_key?
563
- ids.map { |values_set| relation.where(primary_key.zip(values_set).to_h) }.inject(&:or)
564
- else
565
- relation.where(primary_key => ids)
566
- end
557
+ relation = relation.where(primary_key => ids)
567
558
  relation = relation.select(table[primary_key]) unless select_values.empty?
568
559
  result = relation.records
569
560
 
@@ -34,19 +34,17 @@ module ActiveRecord
34
34
  end
35
35
 
36
36
  def klass(value)
37
- case value
38
- when Base
37
+ if value.is_a?(Base)
39
38
  value.class
40
- when Relation
39
+ elsif value.is_a?(Relation)
41
40
  value.klass
42
41
  end
43
42
  end
44
43
 
45
44
  def convert_to_id(value)
46
- case value
47
- when Base
45
+ if value.is_a?(Base)
48
46
  value._read_attribute(primary_key(value))
49
- when Relation
47
+ elsif value.is_a?(Relation)
50
48
  value.select(primary_key(value))
51
49
  else
52
50
  value
@@ -57,6 +57,7 @@ module ActiveRecord
57
57
 
58
58
  def dump(stream)
59
59
  header(stream)
60
+ schemas(stream)
60
61
  extensions(stream)
61
62
  types(stream)
62
63
  tables(stream)
@@ -119,6 +120,10 @@ module ActiveRecord
119
120
  def types(stream)
120
121
  end
121
122
 
123
+ # schemas are only supported by PostgreSQL
124
+ def schemas(stream)
125
+ end
126
+
122
127
  def tables(stream)
123
128
  sorted_tables = @connection.tables.sort
124
129
 
@@ -188,7 +193,7 @@ module ActiveRecord
188
193
  indexes_in_create(table, tbl)
189
194
  check_constraints_in_create(table, tbl) if @connection.supports_check_constraints?
190
195
  exclusion_constraints_in_create(table, tbl) if @connection.supports_exclusion_constraints?
191
- unique_keys_in_create(table, tbl) if @connection.supports_unique_keys?
196
+ unique_constraints_in_create(table, tbl) if @connection.supports_unique_constraints?
192
197
 
193
198
  tbl.puts " end"
194
199
  tbl.puts
@@ -224,10 +229,10 @@ module ActiveRecord
224
229
  indexes = indexes.reject { |index| exclusion_constraint_names.include?(index.name) }
225
230
  end
226
231
 
227
- if @connection.supports_unique_keys? && (unique_keys = @connection.unique_keys(table)).any?
228
- unique_key_names = unique_keys.collect(&:name)
232
+ if @connection.supports_unique_constraints? && (unique_constraints = @connection.unique_constraints(table)).any?
233
+ unique_constraint_names = unique_constraints.collect(&:name)
229
234
 
230
- indexes = indexes.reject { |index| unique_key_names.include?(index.name) }
235
+ indexes = indexes.reject { |index| unique_constraint_names.include?(index.name) }
231
236
  end
232
237
 
233
238
  index_statements = indexes.map do |index|
@@ -23,6 +23,7 @@ module ActiveRecord
23
23
  db_path = db_config.database
24
24
  file = File.absolute_path?(db_path) ? db_path : File.join(root, db_path)
25
25
  FileUtils.rm(file)
26
+ FileUtils.rm_f(["#{file}-shm", "#{file}-wal"])
26
27
  rescue Errno::ENOENT => error
27
28
  raise NoDatabaseError.new(error.message)
28
29
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0.beta1
4
+ version: 7.1.0.rc2
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Heinemeier Hansson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-13 00:00:00.000000000 Z
11
+ date: 2023-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -16,28 +16,28 @@ dependencies:
16
16
  requirements:
17
17
  - - '='
18
18
  - !ruby/object:Gem::Version
19
- version: 7.1.0.beta1
19
+ version: 7.1.0.rc2
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
- version: 7.1.0.beta1
26
+ version: 7.1.0.rc2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activemodel
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - '='
32
32
  - !ruby/object:Gem::Version
33
- version: 7.1.0.beta1
33
+ version: 7.1.0.rc2
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - '='
39
39
  - !ruby/object:Gem::Version
40
- version: 7.1.0.beta1
40
+ version: 7.1.0.rc2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: timeout
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -469,10 +469,10 @@ licenses:
469
469
  - MIT
470
470
  metadata:
471
471
  bug_tracker_uri: https://github.com/rails/rails/issues
472
- changelog_uri: https://github.com/rails/rails/blob/v7.1.0.beta1/activerecord/CHANGELOG.md
473
- documentation_uri: https://api.rubyonrails.org/v7.1.0.beta1/
472
+ changelog_uri: https://github.com/rails/rails/blob/v7.1.0.rc2/activerecord/CHANGELOG.md
473
+ documentation_uri: https://api.rubyonrails.org/v7.1.0.rc2/
474
474
  mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
475
- source_code_uri: https://github.com/rails/rails/tree/v7.1.0.beta1/activerecord
475
+ source_code_uri: https://github.com/rails/rails/tree/v7.1.0.rc2/activerecord
476
476
  rubygems_mfa_required: 'true'
477
477
  post_install_message:
478
478
  rdoc_options: