activerecord 7.1.0.beta1 → 7.1.0.rc2
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.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +85 -4
- data/lib/active_record/associations/collection_association.rb +1 -3
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations.rb +110 -110
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +20 -1
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -9
- data/lib/active_record/connection_adapters/abstract_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +7 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/pool_manager.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +0 -16
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +5 -5
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -24
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -8
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +25 -29
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -6
- data/lib/active_record/connection_adapters/schema_cache.rb +2 -2
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +49 -4
- data/lib/active_record/core.rb +7 -9
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +1 -1
- data/lib/active_record/errors.rb +19 -0
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/migration/command_recorder.rb +8 -8
- data/lib/active_record/nested_attributes.rb +0 -5
- data/lib/active_record/normalization.rb +2 -1
- data/lib/active_record/persistence.rb +1 -1
- data/lib/active_record/querying.rb +2 -2
- data/lib/active_record/railtie.rb +1 -1
- data/lib/active_record/reflection.rb +10 -16
- data/lib/active_record/relation/calculations.rb +8 -8
- data/lib/active_record/relation/finder_methods.rb +3 -12
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/schema_dumper.rb +9 -4
- data/lib/active_record/tasks/sqlite_database_tasks.rb +1 -0
- 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 /^'( | 
| 468 | 
            +
                      when /^'([^|]*)'$/m
         | 
| 455 469 | 
             
                        $1.gsub("''", "'")
         | 
| 456 470 | 
             
                      # Quoted types
         | 
| 457 | 
            -
                      when /^"( | 
| 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 | 
            -
                      @ | 
| 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)
         | 
    
        data/lib/active_record/core.rb
    CHANGED
    
    | @@ -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. | 
| 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. | 
| 633 | 
            -
                #   => #< | 
| 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 | 
            -
                         | 
| 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)
         | 
    
        data/lib/active_record/errors.rb
    CHANGED
    
    | @@ -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 |  | 
| @@ -12,7 +12,7 @@ module ActiveRecord | |
| 12 12 | 
             
                # * add_foreign_key
         | 
| 13 13 | 
             
                # * add_check_constraint
         | 
| 14 14 | 
             
                # * add_exclusion_constraint
         | 
| 15 | 
            -
                # *  | 
| 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 | 
            -
                # *  | 
| 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 | 
            -
                    : | 
| 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 | 
            -
                           | 
| 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  | 
| 332 | 
            +
                    def invert_add_unique_constraint(args)
         | 
| 333 333 | 
             
                      options = args.dup.extract_options!
         | 
| 334 334 |  | 
| 335 | 
            -
                      raise ActiveRecord::IrreversibleMigration, " | 
| 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  | 
| 339 | 
            +
                    def invert_remove_unique_constraint(args)
         | 
| 340 340 | 
             
                      _table, columns = args.dup.tap(&:extract_options!)
         | 
| 341 341 |  | 
| 342 | 
            -
                      raise ActiveRecord::IrreversibleMigration, " | 
| 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+ -  | 
| 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}=#{ | 
| 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. | 
| 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( | 
| 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( | 
| 774 | 
            -
                      primary_query_constraints =  | 
| 775 | 
            -
                      owner_pk =  | 
| 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 `#{ | 
| 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 `#{ | 
| 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 `#{ | 
| 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  | 
| 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 =  | 
| 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 =  | 
| 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 | 
            -
                       | 
| 38 | 
            -
                      when Base
         | 
| 37 | 
            +
                      if value.is_a?(Base)
         | 
| 39 38 | 
             
                        value.class
         | 
| 40 | 
            -
                       | 
| 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 | 
            -
                       | 
| 47 | 
            -
                      when Base
         | 
| 45 | 
            +
                      if value.is_a?(Base)
         | 
| 48 46 | 
             
                        value._read_attribute(primary_key(value))
         | 
| 49 | 
            -
                       | 
| 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 | 
            -
                       | 
| 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. | 
| 228 | 
            -
                         | 
| 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|  | 
| 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. | 
| 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- | 
| 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. | 
| 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. | 
| 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. | 
| 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. | 
| 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. | 
| 473 | 
            -
              documentation_uri: https://api.rubyonrails.org/v7.1.0. | 
| 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. | 
| 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:
         |