activerecord 7.0.3.1 → 7.0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +128 -0
- data/lib/active_record/associations/collection_association.rb +0 -1
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +7 -4
- data/lib/active_record/associations/join_dependency.rb +17 -13
- data/lib/active_record/associations.rb +6 -6
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -0
- data/lib/active_record/coders/yaml_column.rb +11 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +10 -1
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +5 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +7 -2
- data/lib/active_record/delegated_type.rb +1 -1
- data/lib/active_record/encryption/message.rb +1 -1
- data/lib/active_record/encryption/properties.rb +1 -1
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +1 -1
- data/lib/active_record/model_schema.rb +21 -9
- data/lib/active_record/query_logs.rb +12 -1
- data/lib/active_record/railtie.rb +6 -34
- data/lib/active_record/railties/databases.rake +15 -10
- data/lib/active_record/relation/query_methods.rb +21 -5
- data/lib/active_record/relation.rb +1 -0
- data/lib/active_record/scoping/default.rb +4 -2
- data/lib/active_record/signed_id.rb +1 -1
- data/lib/active_record/store.rb +7 -2
- data/lib/active_record/test_fixtures.rb +9 -5
- data/lib/active_record.rb +9 -1
- metadata +10 -10
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 3a5c0c6f9ce9d898d0ec937ec3d4c6ea37ae02637d8aee9cf219ac5acdec5236
         | 
| 4 | 
            +
              data.tar.gz: 2d19932b94835dcbd398676c2528177c11f9437edc7068f44f314449ccb5abe0
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: f3746715cb1a4b90ed3ce96f4826006657d450215af9f96179e53ad32b967dbad06d0328e6c18e0eedf3a576fe5efedc9c546c07149801b90c4e5eb537a3962c
         | 
| 7 | 
            +
              data.tar.gz: a5cf64d8fbaf1023b35d22865468a824ae13a3c243b3c1084bbfafcad432a84df322346b9143a6e98273202da674bf0d3e521d903ad450209fc014998127e223
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,131 @@ | |
| 1 | 
            +
            ## Rails 7.0.4.1 (January 17, 2023) ##
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            *   Make sanitize_as_sql_comment more strict
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                Though this method was likely never meant to take user input, it was
         | 
| 6 | 
            +
                attempting sanitization. That sanitization could be bypassed with
         | 
| 7 | 
            +
                carefully crafted input.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                This commit makes the sanitization more robust by replacing any
         | 
| 10 | 
            +
                occurrances of "/*" or "*/" with "/ *" or "* /". It also performs a
         | 
| 11 | 
            +
                first pass to remove one surrounding comment to avoid compatibility
         | 
| 12 | 
            +
                issues for users relying on the existing removal.
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                This also clarifies in the documentation of annotate that it should not
         | 
| 15 | 
            +
                be provided user input.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                [CVE-2023-22794]
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            *   Added integer width check to PostgreSQL::Quoting
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                Given a value outside the range for a 64bit signed integer type
         | 
| 22 | 
            +
                PostgreSQL will treat the column type as numeric. Comparing
         | 
| 23 | 
            +
                integer values against numeric values can result in a slow
         | 
| 24 | 
            +
                sequential scan.
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                This behavior is configurable via
         | 
| 27 | 
            +
                ActiveRecord::Base.raise_int_wider_than_64bit which defaults to true.
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                [CVE-2022-44566]
         | 
| 30 | 
            +
             | 
| 31 | 
            +
             | 
| 32 | 
            +
            ## Rails 7.0.4 (September 09, 2022) ##
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            *   Symbol is allowed by default for YAML columns
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                *Étienne Barrié*
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            *   Fix `ActiveRecord::Store` to serialize as a regular Hash
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                Previously it would serialize as an `ActiveSupport::HashWithIndifferentAccess`
         | 
| 41 | 
            +
                which is wasteful and cause problem with YAML safe_load.
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                *Jean Boussier*
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            *   Add `timestamptz` as a time zone aware type for PostgreSQL
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                This is required for correctly parsing `timestamp with time zone` values in your database.
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                If you don't want this, you can opt out by adding this initializer:
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                ```ruby
         | 
| 52 | 
            +
                ActiveRecord::Base.time_zone_aware_types -= [:timestamptz]
         | 
| 53 | 
            +
                ```
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                *Alex Ghiculescu*
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            *   Fix supporting timezone awareness for `tsrange` and `tstzrange` array columns.
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                ```ruby
         | 
| 60 | 
            +
                # In database migrations
         | 
| 61 | 
            +
                add_column :shops, :open_hours, :tsrange, array: true
         | 
| 62 | 
            +
                # In app config
         | 
| 63 | 
            +
                ActiveRecord::Base.time_zone_aware_types += [:tsrange]
         | 
| 64 | 
            +
                # In the code times are properly converted to app time zone
         | 
| 65 | 
            +
                Shop.create!(open_hours: [Time.current..8.hour.from_now])
         | 
| 66 | 
            +
                ```
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                *Wojciech Wnętrzak*
         | 
| 69 | 
            +
             | 
| 70 | 
            +
            *   Resolve issue where a relation cache_version could be left stale.
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                Previously, when `reset` was called on a relation object it did not reset the cache_versions
         | 
| 73 | 
            +
                ivar. This led to a confusing situation where despite having the correct data the relation
         | 
| 74 | 
            +
                still reported a stale cache_version.
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                Usage:
         | 
| 77 | 
            +
             | 
| 78 | 
            +
                ```ruby
         | 
| 79 | 
            +
                developers = Developer.all
         | 
| 80 | 
            +
                developers.cache_version
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                Developer.update_all(updated_at: Time.now.utc + 1.second)
         | 
| 83 | 
            +
             | 
| 84 | 
            +
                developers.cache_version # Stale cache_version
         | 
| 85 | 
            +
                developers.reset
         | 
| 86 | 
            +
                developers.cache_version # Returns the current correct cache_version
         | 
| 87 | 
            +
                ```
         | 
| 88 | 
            +
             | 
| 89 | 
            +
                Fixes #45341.
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                *Austen Madden*
         | 
| 92 | 
            +
             | 
| 93 | 
            +
            *   Fix `load_async` when called on an association proxy.
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                Calling `load_async` directly an association would schedule
         | 
| 96 | 
            +
                a query but never use it.
         | 
| 97 | 
            +
             | 
| 98 | 
            +
                ```ruby
         | 
| 99 | 
            +
                comments = post.comments.load_async # schedule a query
         | 
| 100 | 
            +
                comments.to_a # perform an entirely new sync query
         | 
| 101 | 
            +
                ```
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                Now it does use the async query, however note that it doesn't
         | 
| 104 | 
            +
                cause the association to be loaded.
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                *Jean Boussier*
         | 
| 107 | 
            +
             | 
| 108 | 
            +
            *   Fix eager loading for models without primary keys.
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                *Anmol Chopra*, *Matt Lawrence*, and *Jonathan Hefner*
         | 
| 111 | 
            +
             | 
| 112 | 
            +
            *   `rails db:schema:{dump,load}` now checks `ENV["SCHEMA_FORMAT"]` before config
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                Since `rails db:structure:{dump,load}` was deprecated there wasn't a simple
         | 
| 115 | 
            +
                way to dump a schema to both SQL and Ruby formats. You can now do this with
         | 
| 116 | 
            +
                an environment variable. For example:
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                ```
         | 
| 119 | 
            +
                SCHEMA_FORMAT=sql rake db:schema:dump
         | 
| 120 | 
            +
                ```
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                *Alex Ghiculescu*
         | 
| 123 | 
            +
             | 
| 124 | 
            +
            *   Fix Hstore deserialize regression.
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                *edsharp*
         | 
| 127 | 
            +
             | 
| 128 | 
            +
             | 
| 1 129 | 
             
            ## Rails 7.0.3.1 (July 12, 2022) ##
         | 
| 2 130 |  | 
| 3 131 | 
             
            *   Change ActiveRecord::Coders::YAMLColumn default to safe_load
         | 
| @@ -320,7 +320,6 @@ module ActiveRecord | |
| 320 320 | 
             
                    #   * Otherwise, attributes should have the value found in the database
         | 
| 321 321 | 
             
                    def merge_target_lists(persisted, memory)
         | 
| 322 322 | 
             
                      return persisted if memory.empty?
         | 
| 323 | 
            -
                      return memory    if persisted.empty?
         | 
| 324 323 |  | 
| 325 324 | 
             
                      persisted.map! do |record|
         | 
| 326 325 | 
             
                        if mem_record = memory.delete(record)
         | 
| @@ -1108,7 +1108,7 @@ module ActiveRecord | |
| 1108 1108 | 
             
                  ].flat_map { |klass|
         | 
| 1109 1109 | 
             
                    klass.public_instance_methods(false)
         | 
| 1110 1110 | 
             
                  } - self.public_instance_methods(false) - [:select] + [
         | 
| 1111 | 
            -
                    :scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all
         | 
| 1111 | 
            +
                    :scoping, :values, :insert, :insert_all, :insert!, :insert_all!, :upsert, :upsert_all, :load_async
         | 
| 1112 1112 | 
             
                  ]
         | 
| 1113 1113 |  | 
| 1114 1114 | 
             
                  delegate(*delegate_methods, to: :scope)
         | 
| @@ -79,10 +79,13 @@ module ActiveRecord | |
| 79 79 | 
             
                        scope.count(:all)
         | 
| 80 80 | 
             
                      end
         | 
| 81 81 |  | 
| 82 | 
            -
                      # If there's nothing in the database  | 
| 83 | 
            -
                      #  | 
| 84 | 
            -
                      #  | 
| 85 | 
            -
                       | 
| 82 | 
            +
                      # If there's nothing in the database, @target should only contain new
         | 
| 83 | 
            +
                      # records or be an empty array. This is a documented side-effect of
         | 
| 84 | 
            +
                      # the method that may avoid an extra SELECT.
         | 
| 85 | 
            +
                      if count == 0
         | 
| 86 | 
            +
                        target.select!(&:new_record?)
         | 
| 87 | 
            +
                        loaded!
         | 
| 88 | 
            +
                      end
         | 
| 86 89 |  | 
| 87 90 | 
             
                      [association_scope.limit_value, count].compact.min
         | 
| 88 91 | 
             
                    end
         | 
| @@ -252,35 +252,39 @@ module ActiveRecord | |
| 252 252 | 
             
                          next
         | 
| 253 253 | 
             
                        end
         | 
| 254 254 |  | 
| 255 | 
            -
                         | 
| 256 | 
            -
             | 
| 257 | 
            -
             | 
| 255 | 
            +
                        if node.primary_key
         | 
| 256 | 
            +
                          key = aliases.column_alias(node, node.primary_key)
         | 
| 257 | 
            +
                          id = row[key]
         | 
| 258 | 
            +
                        else
         | 
| 259 | 
            +
                          key = aliases.column_alias(node, node.reflection.join_primary_key.to_s)
         | 
| 260 | 
            +
                          id = nil # Avoid id-based model caching.
         | 
| 261 | 
            +
                        end
         | 
| 262 | 
            +
             | 
| 263 | 
            +
                        if row[key].nil?
         | 
| 258 264 | 
             
                          nil_association = ar_parent.association(node.reflection.name)
         | 
| 259 265 | 
             
                          nil_association.loaded!
         | 
| 260 266 | 
             
                          next
         | 
| 261 267 | 
             
                        end
         | 
| 262 268 |  | 
| 263 | 
            -
                        model = seen[ar_parent][node][id]
         | 
| 264 | 
            -
             | 
| 265 | 
            -
                        if model
         | 
| 266 | 
            -
                          construct(model, node, row, seen, model_cache, strict_loading_value)
         | 
| 267 | 
            -
                        else
         | 
| 269 | 
            +
                        unless model = seen[ar_parent][node][id]
         | 
| 268 270 | 
             
                          model = construct_model(ar_parent, node, row, model_cache, id, strict_loading_value)
         | 
| 269 | 
            -
             | 
| 270 | 
            -
                          seen[ar_parent][node][id] = model
         | 
| 271 | 
            -
                          construct(model, node, row, seen, model_cache, strict_loading_value)
         | 
| 271 | 
            +
                          seen[ar_parent][node][id] = model if id
         | 
| 272 272 | 
             
                        end
         | 
| 273 | 
            +
             | 
| 274 | 
            +
                        construct(model, node, row, seen, model_cache, strict_loading_value)
         | 
| 273 275 | 
             
                      end
         | 
| 274 276 | 
             
                    end
         | 
| 275 277 |  | 
| 276 278 | 
             
                    def construct_model(record, node, row, model_cache, id, strict_loading_value)
         | 
| 277 279 | 
             
                      other = record.association(node.reflection.name)
         | 
| 278 280 |  | 
| 279 | 
            -
                      model = model_cache[node][id] | 
| 280 | 
            -
                        node.instantiate(row, aliases.column_aliases(node)) do |m|
         | 
| 281 | 
            +
                      unless model = model_cache[node][id]
         | 
| 282 | 
            +
                        model = node.instantiate(row, aliases.column_aliases(node)) do |m|
         | 
| 281 283 | 
             
                          m.strict_loading! if strict_loading_value
         | 
| 282 284 | 
             
                          other.set_inverse_instance(m)
         | 
| 283 285 | 
             
                        end
         | 
| 286 | 
            +
                        model_cache[node][id] = model if id
         | 
| 287 | 
            +
                      end
         | 
| 284 288 |  | 
| 285 289 | 
             
                      if node.reflection.collection?
         | 
| 286 290 | 
             
                        other.target.push(model)
         | 
| @@ -628,15 +628,15 @@ module ActiveRecord | |
| 628 628 | 
             
                  #
         | 
| 629 629 | 
             
                  # Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
         | 
| 630 630 | 
             
                  #
         | 
| 631 | 
            -
                  # | 
| 632 | 
            -
                  # | 
| 633 | 
            -
                  # | 
| 631 | 
            +
                  # * <tt>firm.clients.destroy(client)</tt>
         | 
| 632 | 
            +
                  # * <tt>firm.clients.destroy(*clients)</tt>
         | 
| 633 | 
            +
                  # * <tt>firm.clients.destroy_all</tt>
         | 
| 634 634 | 
             
                  #
         | 
| 635 635 | 
             
                  # +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
         | 
| 636 636 | 
             
                  #
         | 
| 637 | 
            -
                  # | 
| 638 | 
            -
                  # | 
| 639 | 
            -
                  # | 
| 637 | 
            +
                  # * <tt>firm.clients.delete(client)</tt>
         | 
| 638 | 
            +
                  # * <tt>firm.clients.delete(*clients)</tt>
         | 
| 639 | 
            +
                  # * <tt>firm.clients.delete_all</tt>
         | 
| 640 640 | 
             
                  #
         | 
| 641 641 | 
             
                  # == Association extensions
         | 
| 642 642 | 
             
                  #
         | 
| @@ -19,6 +19,8 @@ module ActiveRecord | |
| 19 19 |  | 
| 20 20 | 
             
                      if value.is_a?(Hash)
         | 
| 21 21 | 
             
                        set_time_zone_without_conversion(super)
         | 
| 22 | 
            +
                      elsif value.is_a?(Range)
         | 
| 23 | 
            +
                        Range.new(user_input_in_time_zone(value.begin), user_input_in_time_zone(value.end), value.exclude_end?)
         | 
| 22 24 | 
             
                      elsif value.respond_to?(:in_time_zone)
         | 
| 23 25 | 
             
                        begin
         | 
| 24 26 | 
             
                          super(user_input_in_time_zone(value)) || super
         | 
| @@ -40,6 +42,8 @@ module ActiveRecord | |
| 40 42 | 
             
                          value.in_time_zone
         | 
| 41 43 | 
             
                        elsif value.respond_to?(:infinite?) && value.infinite?
         | 
| 42 44 | 
             
                          value
         | 
| 45 | 
            +
                        elsif value.is_a?(Range)
         | 
| 46 | 
            +
                          Range.new(convert_time_to_time_zone(value.begin), convert_time_to_time_zone(value.end), value.exclude_end?)
         | 
| 43 47 | 
             
                        else
         | 
| 44 48 | 
             
                          map_avoiding_infinite_recursion(value) { |v| convert_time_to_time_zone(v) }
         | 
| 45 49 | 
             
                        end
         | 
| @@ -45,14 +45,20 @@ module ActiveRecord | |
| 45 45 | 
             
                      raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
         | 
| 46 46 | 
             
                    end
         | 
| 47 47 |  | 
| 48 | 
            -
                     | 
| 49 | 
            -
                       | 
| 50 | 
            -
                         | 
| 51 | 
            -
                      else
         | 
| 52 | 
            -
                        if YAML.respond_to?(:unsafe_load)
         | 
| 48 | 
            +
                    if YAML.respond_to?(:unsafe_load)
         | 
| 49 | 
            +
                      def yaml_load(payload)
         | 
| 50 | 
            +
                        if ActiveRecord.use_yaml_unsafe_load
         | 
| 53 51 | 
             
                          YAML.unsafe_load(payload)
         | 
| 54 52 | 
             
                        else
         | 
| 53 | 
            +
                          YAML.safe_load(payload, permitted_classes: ActiveRecord.yaml_column_permitted_classes, aliases: true)
         | 
| 54 | 
            +
                        end
         | 
| 55 | 
            +
                      end
         | 
| 56 | 
            +
                    else
         | 
| 57 | 
            +
                      def yaml_load(payload)
         | 
| 58 | 
            +
                        if ActiveRecord.use_yaml_unsafe_load
         | 
| 55 59 | 
             
                          YAML.load(payload)
         | 
| 60 | 
            +
                        else
         | 
| 61 | 
            +
                          YAML.safe_load(payload, permitted_classes: ActiveRecord.yaml_column_permitted_classes, aliases: true)
         | 
| 56 62 | 
             
                        end
         | 
| 57 63 | 
             
                      end
         | 
| 58 64 | 
             
                    end
         | 
| @@ -146,7 +146,16 @@ module ActiveRecord | |
| 146 146 | 
             
                  end
         | 
| 147 147 |  | 
| 148 148 | 
             
                  def sanitize_as_sql_comment(value) # :nodoc:
         | 
| 149 | 
            -
                     | 
| 149 | 
            +
                    # Sanitize a string to appear within a SQL comment
         | 
| 150 | 
            +
                    # For compatibility, this also surrounding "/*+", "/*", and "*/"
         | 
| 151 | 
            +
                    # charcacters, possibly with single surrounding space.
         | 
| 152 | 
            +
                    # Then follows that by replacing any internal "*/" or "/ *" with
         | 
| 153 | 
            +
                    # "* /" or "/ *"
         | 
| 154 | 
            +
                    comment = value.to_s.dup
         | 
| 155 | 
            +
                    comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
         | 
| 156 | 
            +
                    comment.gsub!("*/", "* /")
         | 
| 157 | 
            +
                    comment.gsub!("/*", "/ *")
         | 
| 158 | 
            +
                    comment
         | 
| 150 159 | 
             
                  end
         | 
| 151 160 |  | 
| 152 161 | 
             
                  def column_name_matcher # :nodoc:
         | 
| @@ -139,7 +139,7 @@ module ActiveRecord | |
| 139 139 | 
             
                  end
         | 
| 140 140 |  | 
| 141 141 | 
             
                  def field_ordered_value(column, values) # :nodoc:
         | 
| 142 | 
            -
                    field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse])
         | 
| 142 | 
            +
                    field = Arel::Nodes::NamedFunction.new("FIELD", [column, values.reverse.map { |value| Arel::Nodes.build_quoted(value) }])
         | 
| 143 143 | 
             
                    Arel::Nodes::Descending.new(field)
         | 
| 144 144 | 
             
                  end
         | 
| 145 145 |  | 
| @@ -711,6 +711,10 @@ module ActiveRecord | |
| 711 711 | 
             
                        options[:comment] = column.comment
         | 
| 712 712 | 
             
                      end
         | 
| 713 713 |  | 
| 714 | 
            +
                      unless options.key?(:collation)
         | 
| 715 | 
            +
                        options[:collation] = column.collation
         | 
| 716 | 
            +
                      end
         | 
| 717 | 
            +
             | 
| 714 718 | 
             
                      unless options.key?(:auto_increment)
         | 
| 715 719 | 
             
                        options[:auto_increment] = column.auto_increment?
         | 
| 716 720 | 
             
                      end
         | 
| @@ -159,7 +159,7 @@ module ActiveRecord | |
| 159 159 | 
             
                      end
         | 
| 160 160 |  | 
| 161 161 | 
             
                      def default_type(table_name, field_name)
         | 
| 162 | 
            -
                        match = create_table_info(table_name) | 
| 162 | 
            +
                        match = create_table_info(table_name)&.match(/`#{field_name}` (.+) DEFAULT ('|\d+|[A-z]+)/)
         | 
| 163 163 | 
             
                        default_pre = match[2] if match
         | 
| 164 164 |  | 
| 165 165 | 
             
                        if default_pre == "'"
         | 
| @@ -26,7 +26,7 @@ module ActiveRecord | |
| 26 26 | 
             
                            raise(ArgumentError, ERROR % scanner.string.inspect)
         | 
| 27 27 | 
             
                          end
         | 
| 28 28 |  | 
| 29 | 
            -
                          unless key = scanner. | 
| 29 | 
            +
                          unless key = scanner.scan(/^(\\[\\"]|[^\\"])*?(?=")/)
         | 
| 30 30 | 
             
                            raise(ArgumentError, ERROR % scanner.string.inspect)
         | 
| 31 31 | 
             
                          end
         | 
| 32 32 |  | 
| @@ -41,7 +41,7 @@ module ActiveRecord | |
| 41 41 | 
             
                              raise(ArgumentError, ERROR % scanner.string.inspect)
         | 
| 42 42 | 
             
                            end
         | 
| 43 43 |  | 
| 44 | 
            -
                            unless value = scanner. | 
| 44 | 
            +
                            unless value = scanner.scan(/^(\\[\\"]|[^\\"])*?(?=")/)
         | 
| 45 45 | 
             
                              raise(ArgumentError, ERROR % scanner.string.inspect)
         | 
| 46 46 | 
             
                            end
         | 
| 47 47 |  | 
| @@ -4,6 +4,12 @@ module ActiveRecord | |
| 4 4 | 
             
              module ConnectionAdapters
         | 
| 5 5 | 
             
                module PostgreSQL
         | 
| 6 6 | 
             
                  module Quoting
         | 
| 7 | 
            +
                    class IntegerOutOf64BitRange < StandardError
         | 
| 8 | 
            +
                      def initialize(msg)
         | 
| 9 | 
            +
                        super(msg)
         | 
| 10 | 
            +
                      end
         | 
| 11 | 
            +
                    end
         | 
| 12 | 
            +
             | 
| 7 13 | 
             
                    # Escapes binary strings for bytea input to the database.
         | 
| 8 14 | 
             
                    def escape_bytea(value)
         | 
| 9 15 | 
             
                      @connection.escape_bytea(value) if value
         | 
| @@ -16,7 +22,27 @@ module ActiveRecord | |
| 16 22 | 
             
                      @connection.unescape_bytea(value) if value
         | 
| 17 23 | 
             
                    end
         | 
| 18 24 |  | 
| 25 | 
            +
                    def check_int_in_range(value)
         | 
| 26 | 
            +
                      if value.to_int > 9223372036854775807 || value.to_int < -9223372036854775808
         | 
| 27 | 
            +
                        exception = <<~ERROR
         | 
| 28 | 
            +
                          Provided value outside of the range of a signed 64bit integer.
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                          PostgreSQL will treat the column type in question as a numeric.
         | 
| 31 | 
            +
                          This may result in a slow sequential scan due to a comparison
         | 
| 32 | 
            +
                          being performed between an integer or bigint value and a numeric value.
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                          To allow for this potentially unwanted behavior, set
         | 
| 35 | 
            +
                          ActiveRecord.raise_int_wider_than_64bit to false.
         | 
| 36 | 
            +
                        ERROR
         | 
| 37 | 
            +
                        raise IntegerOutOf64BitRange.new exception
         | 
| 38 | 
            +
                      end
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 19 41 | 
             
                    def quote(value) # :nodoc:
         | 
| 42 | 
            +
                      if ActiveRecord.raise_int_wider_than_64bit && value.is_a?(Integer)
         | 
| 43 | 
            +
                        check_int_in_range(value)
         | 
| 44 | 
            +
                      end
         | 
| 45 | 
            +
             | 
| 20 46 | 
             
                      case value
         | 
| 21 47 | 
             
                      when OID::Xml::Data
         | 
| 22 48 | 
             
                        "xml '#{quote_string(value.to_s)}'"
         | 
| @@ -45,8 +45,10 @@ Rails needs superuser privileges to disable referential integrity. | |
| 45 45 | 
             
                        BEGIN
         | 
| 46 46 | 
             
                        FOR r IN (
         | 
| 47 47 | 
             
                          SELECT FORMAT(
         | 
| 48 | 
            -
                            'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I''; ALTER TABLE %I VALIDATE CONSTRAINT %I;',
         | 
| 48 | 
            +
                            'UPDATE pg_constraint SET convalidated=false WHERE conname = ''%I'' AND connamespace::regnamespace = ''%I''::regnamespace; ALTER TABLE %I.%I VALIDATE CONSTRAINT %I;',
         | 
| 49 49 | 
             
                            constraint_name,
         | 
| 50 | 
            +
                            table_schema,
         | 
| 51 | 
            +
                            table_schema,
         | 
| 50 52 | 
             
                            table_name,
         | 
| 51 53 | 
             
                            constraint_name
         | 
| 52 54 | 
             
                          ) AS constraint_check
         | 
| @@ -1063,5 +1063,6 @@ module ActiveRecord | |
| 1063 1063 | 
             
                    ActiveRecord::Type.register(:vector, OID::Vector, adapter: :postgresql)
         | 
| 1064 1064 | 
             
                    ActiveRecord::Type.register(:xml, OID::Xml, adapter: :postgresql)
         | 
| 1065 1065 | 
             
                end
         | 
| 1066 | 
            +
                ActiveSupport.run_load_hooks(:active_record_postgresqladapter, PostgreSQLAdapter)
         | 
| 1066 1067 | 
             
              end
         | 
| 1067 1068 | 
             
            end
         | 
| @@ -21,7 +21,7 @@ module ActiveRecord | |
| 21 21 | 
             
                          WHERE name = #{quote(row['name'])} AND type = 'index'
         | 
| 22 22 | 
             
                        SQL
         | 
| 23 23 |  | 
| 24 | 
            -
                        /\bON\b\s*"?(\w+?)"?\s*\((?<expressions>.+?)\)(?:\s*WHERE\b\s*(?<where>.+))?\z/i =~ index_sql
         | 
| 24 | 
            +
                        /\bON\b\s*"?(\w+?)"?\s*\((?<expressions>.+?)\)(?:\s*WHERE\b\s*(?<where>.+))?(?:\s*\/\*.*\*\/)?\z/i =~ index_sql
         | 
| 25 25 |  | 
| 26 26 | 
             
                        columns = exec_query("PRAGMA index_info(#{quote(row['name'])})", "SCHEMA").map do |col|
         | 
| 27 27 | 
             
                          col["name"]
         | 
| @@ -341,7 +341,7 @@ module ActiveRecord | |
| 341 341 | 
             
                  end
         | 
| 342 342 |  | 
| 343 343 | 
             
                  def get_database_version # :nodoc:
         | 
| 344 | 
            -
                    SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)"))
         | 
| 344 | 
            +
                    SQLite3Adapter::Version.new(query_value("SELECT sqlite_version(*)", "SCHEMA"))
         | 
| 345 345 | 
             
                  end
         | 
| 346 346 |  | 
| 347 347 | 
             
                  def check_version # :nodoc:
         | 
| @@ -477,8 +477,13 @@ module ActiveRecord | |
| 477 477 | 
             
                             options[:rename][column.name.to_sym] ||
         | 
| 478 478 | 
             
                             column.name) : column.name
         | 
| 479 479 |  | 
| 480 | 
            +
                          if column.has_default?
         | 
| 481 | 
            +
                            type = lookup_cast_type_from_column(column)
         | 
| 482 | 
            +
                            default = type.deserialize(column.default)
         | 
| 483 | 
            +
                          end
         | 
| 484 | 
            +
             | 
| 480 485 | 
             
                          @definition.column(column_name, column.type,
         | 
| 481 | 
            -
                            limit: column.limit, default:  | 
| 486 | 
            +
                            limit: column.limit, default: default,
         | 
| 482 487 | 
             
                            precision: column.precision, scale: column.scale,
         | 
| 483 488 | 
             
                            null: column.null, collation: column.collation,
         | 
| 484 489 | 
             
                            primary_key: column_name == from_primary_key
         | 
| @@ -136,7 +136,7 @@ module ActiveRecord | |
| 136 136 | 
             
              #     end
         | 
| 137 137 | 
             
              #   end
         | 
| 138 138 | 
             
              #
         | 
| 139 | 
            -
              # Now you can list a bunch of entries, call  | 
| 139 | 
            +
              # Now you can list a bunch of entries, call <tt>Entry#title</tt>, and polymorphism will provide you with the answer.
         | 
| 140 140 | 
             
              #
         | 
| 141 141 | 
             
              # == Nested Attributes
         | 
| 142 142 | 
             
              #
         | 
| @@ -12,7 +12,7 @@ module ActiveRecord | |
| 12 12 | 
             
                #
         | 
| 13 13 | 
             
                #   message.headers.encrypted_data_key # instead of message.headers[:k]
         | 
| 14 14 | 
             
                #
         | 
| 15 | 
            -
                # See +Properties | 
| 15 | 
            +
                # See +Properties::DEFAULT_PROPERTIES+, Key, Message
         | 
| 16 16 | 
             
                class Properties
         | 
| 17 17 | 
             
                  ALLOWED_VALUE_CLASSES = [String, ActiveRecord::Encryption::Message, Numeric, TrueClass, FalseClass, Symbol, NilClass]
         | 
| 18 18 |  | 
| @@ -44,7 +44,7 @@ module ActiveRecord | |
| 44 44 | 
             
                #   config.active_record.database_resolver_context = MyResolver::MySession
         | 
| 45 45 | 
             
                #
         | 
| 46 46 | 
             
                # Note: If you are using `rails new my_app --minimal` you will need to call
         | 
| 47 | 
            -
                # `require "active_support/core_ext/integer/time"` to load the  | 
| 47 | 
            +
                # `require "active_support/core_ext/integer/time"` to load the libraries
         | 
| 48 48 | 
             
                # for +Time+.
         | 
| 49 49 | 
             
                class DatabaseSelector
         | 
| 50 50 | 
             
                  def initialize(app, resolver_klass = nil, context_klass = nil, options = {})
         | 
| @@ -126,6 +126,27 @@ module ActiveRecord | |
| 126 126 | 
             
                # +:immutable_string+. This setting does not affect the behavior of
         | 
| 127 127 | 
             
                # <tt>attribute :foo, :string</tt>. Defaults to false.
         | 
| 128 128 |  | 
| 129 | 
            +
                ##
         | 
| 130 | 
            +
                # :singleton-method: inheritance_column
         | 
| 131 | 
            +
                # :call-seq: inheritance_column
         | 
| 132 | 
            +
                #
         | 
| 133 | 
            +
                # The name of the table column which stores the class name on single-table
         | 
| 134 | 
            +
                # inheritance situations.
         | 
| 135 | 
            +
                #
         | 
| 136 | 
            +
                # The default inheritance column name is +type+, which means it's a
         | 
| 137 | 
            +
                # reserved word inside Active Record. To be able to use single-table
         | 
| 138 | 
            +
                # inheritance with another column name, or to use the column +type+ in
         | 
| 139 | 
            +
                # your own model for something else, you can set +inheritance_column+:
         | 
| 140 | 
            +
                #
         | 
| 141 | 
            +
                #     self.inheritance_column = 'zoink'
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                ##
         | 
| 144 | 
            +
                # :singleton-method: inheritance_column=
         | 
| 145 | 
            +
                # :call-seq: inheritance_column=(column)
         | 
| 146 | 
            +
                #
         | 
| 147 | 
            +
                # Defines the name of the table column which will store the class name on single-table
         | 
| 148 | 
            +
                # inheritance situations.
         | 
| 149 | 
            +
             | 
| 129 150 | 
             
                included do
         | 
| 130 151 | 
             
                  class_attribute :primary_key_prefix_type, instance_writer: false
         | 
| 131 152 | 
             
                  class_attribute :table_name_prefix, instance_writer: false, default: ""
         | 
| @@ -136,15 +157,6 @@ module ActiveRecord | |
| 136 157 | 
             
                  class_attribute :implicit_order_column, instance_accessor: false
         | 
| 137 158 | 
             
                  class_attribute :immutable_strings_by_default, instance_accessor: false
         | 
| 138 159 |  | 
| 139 | 
            -
                  # Defines the name of the table column which will store the class name on single-table
         | 
| 140 | 
            -
                  # inheritance situations.
         | 
| 141 | 
            -
                  #
         | 
| 142 | 
            -
                  # The default inheritance column name is +type+, which means it's a
         | 
| 143 | 
            -
                  # reserved word inside Active Record. To be able to use single-table
         | 
| 144 | 
            -
                  # inheritance with another column name, or to use the column +type+ in
         | 
| 145 | 
            -
                  # your own model for something else, you can set +inheritance_column+:
         | 
| 146 | 
            -
                  #
         | 
| 147 | 
            -
                  #     self.inheritance_column = 'zoink'
         | 
| 148 160 | 
             
                  class_attribute :inheritance_column, instance_accessor: false, default: "type"
         | 
| 149 161 | 
             
                  singleton_class.class_eval do
         | 
| 150 162 | 
             
                    alias_method :_inheritance_column=, :inheritance_column=
         | 
| @@ -33,6 +33,8 @@ module ActiveRecord | |
| 33 33 | 
             
              # want to add to the comment. Dynamic content can be created by setting a proc or lambda value in a hash,
         | 
| 34 34 | 
             
              # and can reference any value stored in the +context+ object.
         | 
| 35 35 | 
             
              #
         | 
| 36 | 
            +
              # Escaping is performed on the string returned, however untrusted user input should not be used.
         | 
| 37 | 
            +
              #
         | 
| 36 38 | 
             
              # Example:
         | 
| 37 39 | 
             
              #
         | 
| 38 40 | 
             
              #    tags = [
         | 
| @@ -109,7 +111,16 @@ module ActiveRecord | |
| 109 111 | 
             
                    end
         | 
| 110 112 |  | 
| 111 113 | 
             
                    def escape_sql_comment(content)
         | 
| 112 | 
            -
                       | 
| 114 | 
            +
                      # Sanitize a string to appear within a SQL comment
         | 
| 115 | 
            +
                      # For compatibility, this also surrounding "/*+", "/*", and "*/"
         | 
| 116 | 
            +
                      # charcacters, possibly with single surrounding space.
         | 
| 117 | 
            +
                      # Then follows that by replacing any internal "*/" or "/ *" with
         | 
| 118 | 
            +
                      # "* /" or "/ *"
         | 
| 119 | 
            +
                      comment = content.to_s.dup
         | 
| 120 | 
            +
                      comment.gsub!(%r{\A\s*/\*\+?\s?|\s?\*/\s*\Z}, "")
         | 
| 121 | 
            +
                      comment.gsub!("*/", "* /")
         | 
| 122 | 
            +
                      comment.gsub!("/*", "/ *")
         | 
| 123 | 
            +
                      comment
         | 
| 113 124 | 
             
                    end
         | 
| 114 125 |  | 
| 115 126 | 
             
                    def tag_content
         | 
| @@ -78,6 +78,12 @@ module ActiveRecord | |
| 78 78 | 
             
                  end
         | 
| 79 79 | 
             
                end
         | 
| 80 80 |  | 
| 81 | 
            +
                initializer "active_record.postgresql_time_zone_aware_types" do
         | 
| 82 | 
            +
                  ActiveSupport.on_load(:active_record_postgresqladapter) do
         | 
| 83 | 
            +
                    ActiveRecord::Base.time_zone_aware_types << :timestamptz
         | 
| 84 | 
            +
                  end
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 81 87 | 
             
                initializer "active_record.logger" do
         | 
| 82 88 | 
             
                  ActiveSupport.on_load(:active_record) { self.logger ||= ::Rails.logger }
         | 
| 83 89 | 
             
                end
         | 
| @@ -94,22 +100,6 @@ module ActiveRecord | |
| 94 100 | 
             
                  end
         | 
| 95 101 | 
             
                end
         | 
| 96 102 |  | 
| 97 | 
            -
                initializer "active_record.database_selector" do
         | 
| 98 | 
            -
                  if options = config.active_record.database_selector
         | 
| 99 | 
            -
                    resolver = config.active_record.database_resolver
         | 
| 100 | 
            -
                    operations = config.active_record.database_resolver_context
         | 
| 101 | 
            -
                    config.app_middleware.use ActiveRecord::Middleware::DatabaseSelector, resolver, operations, options
         | 
| 102 | 
            -
                  end
         | 
| 103 | 
            -
                end
         | 
| 104 | 
            -
             | 
| 105 | 
            -
                initializer "active_record.shard_selector" do
         | 
| 106 | 
            -
                  if resolver = config.active_record.shard_resolver
         | 
| 107 | 
            -
                    options = config.active_record.shard_selector || {}
         | 
| 108 | 
            -
             | 
| 109 | 
            -
                    config.app_middleware.use ActiveRecord::Middleware::ShardSelector, resolver, options
         | 
| 110 | 
            -
                  end
         | 
| 111 | 
            -
                end
         | 
| 112 | 
            -
             | 
| 113 103 | 
             
                initializer "Check for cache versioning support" do
         | 
| 114 104 | 
             
                  config.after_initialize do |app|
         | 
| 115 105 | 
             
                    ActiveSupport.on_load(:active_record) do
         | 
| @@ -403,23 +393,5 @@ To keep using the current cache store, you can turn off cache versioning entirel | |
| 403 393 | 
             
                    end
         | 
| 404 394 | 
             
                  end
         | 
| 405 395 | 
             
                end
         | 
| 406 | 
            -
             | 
| 407 | 
            -
                initializer "active_record.use_yaml_unsafe_load" do |app|
         | 
| 408 | 
            -
                  config.after_initialize do
         | 
| 409 | 
            -
                    unless app.config.active_record.use_yaml_unsafe_load.nil?
         | 
| 410 | 
            -
                      ActiveRecord.use_yaml_unsafe_load =
         | 
| 411 | 
            -
                        app.config.active_record.use_yaml_unsafe_load
         | 
| 412 | 
            -
                    end
         | 
| 413 | 
            -
                  end
         | 
| 414 | 
            -
                end
         | 
| 415 | 
            -
             | 
| 416 | 
            -
                initializer "active_record.yaml_column_permitted_classes" do |app|
         | 
| 417 | 
            -
                  config.after_initialize do
         | 
| 418 | 
            -
                    unless app.config.active_record.yaml_column_permitted_classes.nil?
         | 
| 419 | 
            -
                      ActiveRecord.yaml_column_permitted_classes =
         | 
| 420 | 
            -
                        app.config.active_record.yaml_column_permitted_classes
         | 
| 421 | 
            -
                    end
         | 
| 422 | 
            -
                  end
         | 
| 423 | 
            -
                end
         | 
| 424 396 | 
             
              end
         | 
| 425 397 | 
             
            end
         | 
| @@ -452,30 +452,32 @@ db_namespace = namespace :db do | |
| 452 452 | 
             
              end
         | 
| 453 453 |  | 
| 454 454 | 
             
              namespace :schema do
         | 
| 455 | 
            -
                desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`)"
         | 
| 455 | 
            +
                desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
         | 
| 456 456 | 
             
                task dump: :load_config do
         | 
| 457 457 | 
             
                  ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
         | 
| 458 458 | 
             
                    if db_config.schema_dump
         | 
| 459 459 | 
             
                      ActiveRecord::Base.establish_connection(db_config)
         | 
| 460 | 
            -
                      ActiveRecord | 
| 460 | 
            +
                      schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
         | 
| 461 | 
            +
                      ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
         | 
| 461 462 | 
             
                    end
         | 
| 462 463 | 
             
                  end
         | 
| 463 464 |  | 
| 464 465 | 
             
                  db_namespace["schema:dump"].reenable
         | 
| 465 466 | 
             
                end
         | 
| 466 467 |  | 
| 467 | 
            -
                desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the database"
         | 
| 468 | 
            +
                desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the database"
         | 
| 468 469 | 
             
                task load: [:load_config, :check_protected_environments] do
         | 
| 469 470 | 
             
                  ActiveRecord::Tasks::DatabaseTasks.load_schema_current(ActiveRecord.schema_format, ENV["SCHEMA"])
         | 
| 470 471 | 
             
                end
         | 
| 471 472 |  | 
| 472 473 | 
             
                namespace :dump do
         | 
| 473 474 | 
             
                  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
         | 
| 474 | 
            -
                    desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) for #{name} database"
         | 
| 475 | 
            +
                    desc "Creates a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) for #{name} database"
         | 
| 475 476 | 
             
                    task name => :load_config do
         | 
| 476 477 | 
             
                      db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
         | 
| 477 478 | 
             
                      ActiveRecord::Base.establish_connection(db_config)
         | 
| 478 | 
            -
                      ActiveRecord | 
| 479 | 
            +
                      schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
         | 
| 480 | 
            +
                      ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config, schema_format)
         | 
| 479 481 | 
             
                      db_namespace["schema:dump:#{name}"].reenable
         | 
| 480 482 | 
             
                    end
         | 
| 481 483 | 
             
                  end
         | 
| @@ -483,11 +485,12 @@ db_namespace = namespace :db do | |
| 483 485 |  | 
| 484 486 | 
             
                namespace :load do
         | 
| 485 487 | 
             
                  ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |name|
         | 
| 486 | 
            -
                    desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `config.active_record.schema_format`) into the #{name} database"
         | 
| 488 | 
            +
                    desc "Loads a database schema file (either db/schema.rb or db/structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`) into the #{name} database"
         | 
| 487 489 | 
             
                    task name => [:load_config, :check_protected_environments] do
         | 
| 488 490 | 
             
                      original_db_config = ActiveRecord::Base.connection_db_config
         | 
| 489 491 | 
             
                      db_config = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env, name: name)
         | 
| 490 | 
            -
                      ActiveRecord | 
| 492 | 
            +
                      schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
         | 
| 493 | 
            +
                      ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
         | 
| 491 494 | 
             
                    ensure
         | 
| 492 495 | 
             
                      ActiveRecord::Base.establish_connection(original_db_config) if original_db_config
         | 
| 493 496 | 
             
                    end
         | 
| @@ -545,12 +548,13 @@ db_namespace = namespace :db do | |
| 545 548 | 
             
                  db_namespace["test:load_schema"].invoke
         | 
| 546 549 | 
             
                end
         | 
| 547 550 |  | 
| 548 | 
            -
                # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `config.active_record.schema_format`)"
         | 
| 551 | 
            +
                # desc "Recreate the test database from an existent schema file (schema.rb or structure.sql, depending on `ENV['SCHEMA_FORMAT']` or `config.active_record.schema_format`)"
         | 
| 549 552 | 
             
                task load_schema: %w(db:test:purge) do
         | 
| 550 553 | 
             
                  should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
         | 
| 551 554 | 
             
                  ActiveRecord::Schema.verbose = false
         | 
| 552 555 | 
             
                  ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
         | 
| 553 | 
            -
                    ActiveRecord | 
| 556 | 
            +
                    schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
         | 
| 557 | 
            +
                    ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
         | 
| 554 558 | 
             
                  end
         | 
| 555 559 | 
             
                ensure
         | 
| 556 560 | 
             
                  if should_reconnect
         | 
| @@ -586,7 +590,8 @@ db_namespace = namespace :db do | |
| 586 590 | 
             
                      should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
         | 
| 587 591 | 
             
                      ActiveRecord::Schema.verbose = false
         | 
| 588 592 | 
             
                      db_config = ActiveRecord::Base.configurations.configs_for(env_name: "test", name: name)
         | 
| 589 | 
            -
                      ActiveRecord | 
| 593 | 
            +
                      schema_format = ENV.fetch("SCHEMA_FORMAT", ActiveRecord.schema_format).to_sym
         | 
| 594 | 
            +
                      ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config, schema_format)
         | 
| 590 595 | 
             
                    ensure
         | 
| 591 596 | 
             
                      if should_reconnect
         | 
| 592 597 | 
             
                        ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
         | 
| @@ -10,10 +10,10 @@ module ActiveRecord | |
| 10 10 | 
             
              module QueryMethods
         | 
| 11 11 | 
             
                include ActiveModel::ForbiddenAttributesProtection
         | 
| 12 12 |  | 
| 13 | 
            -
                # WhereChain objects act as placeholder for queries in which  | 
| 14 | 
            -
                # In this case,  | 
| 13 | 
            +
                # WhereChain objects act as placeholder for queries in which +where+ does not have any parameter.
         | 
| 14 | 
            +
                # In this case, +where+ can be chained to return a new relation.
         | 
| 15 15 | 
             
                class WhereChain
         | 
| 16 | 
            -
                  def initialize(scope)
         | 
| 16 | 
            +
                  def initialize(scope) # :nodoc:
         | 
| 17 17 | 
             
                    @scope = scope
         | 
| 18 18 | 
             
                  end
         | 
| 19 19 |  | 
| @@ -717,12 +717,26 @@ module ActiveRecord | |
| 717 717 | 
             
                # === no argument
         | 
| 718 718 | 
             
                #
         | 
| 719 719 | 
             
                # If no argument is passed, #where returns a new instance of WhereChain, that
         | 
| 720 | 
            -
                # can be chained with #not  | 
| 720 | 
            +
                # can be chained with WhereChain#not, WhereChain#missing, or WhereChain#associated.
         | 
| 721 | 
            +
                #
         | 
| 722 | 
            +
                # Chaining with WhereChain#not:
         | 
| 721 723 | 
             
                #
         | 
| 722 724 | 
             
                #    User.where.not(name: "Jon")
         | 
| 723 725 | 
             
                #    # SELECT * FROM users WHERE name != 'Jon'
         | 
| 724 726 | 
             
                #
         | 
| 725 | 
            -
                #  | 
| 727 | 
            +
                # Chaining with WhereChain#associated:
         | 
| 728 | 
            +
                #
         | 
| 729 | 
            +
                #    Post.where.associated(:author)
         | 
| 730 | 
            +
                #    # SELECT "posts".* FROM "posts"
         | 
| 731 | 
            +
                #    # INNER JOIN "authors" ON "authors"."id" = "posts"."author_id"
         | 
| 732 | 
            +
                #    # WHERE "authors"."id" IS NOT NULL
         | 
| 733 | 
            +
                #
         | 
| 734 | 
            +
                # Chaining with WhereChain#missing:
         | 
| 735 | 
            +
                #
         | 
| 736 | 
            +
                #    Post.where.missing(:author)
         | 
| 737 | 
            +
                #    # SELECT "posts".* FROM "posts"
         | 
| 738 | 
            +
                #    # LEFT OUTER JOIN "authors" ON "authors"."id" = "posts"."author_id"
         | 
| 739 | 
            +
                #    # WHERE "authors"."id" IS NULL
         | 
| 726 740 | 
             
                #
         | 
| 727 741 | 
             
                # === blank condition
         | 
| 728 742 | 
             
                #
         | 
| @@ -1202,6 +1216,8 @@ module ActiveRecord | |
| 1202 1216 | 
             
                #   # SELECT "users"."name" FROM "users" /* selecting */ /* user */ /* names */
         | 
| 1203 1217 | 
             
                #
         | 
| 1204 1218 | 
             
                # The SQL block comment delimiters, "/*" and "*/", will be added automatically.
         | 
| 1219 | 
            +
                #
         | 
| 1220 | 
            +
                # Some escaping is performed, however untrusted user input should not be used.
         | 
| 1205 1221 | 
             
                def annotate(*args)
         | 
| 1206 1222 | 
             
                  check_if_method_has_arguments!(__callee__, args)
         | 
| 1207 1223 | 
             
                  spawn.annotate!(*args)
         | 
| @@ -146,11 +146,13 @@ module ActiveRecord | |
| 146 146 | 
             
                          end
         | 
| 147 147 | 
             
                        elsif default_scopes.any?
         | 
| 148 148 | 
             
                          evaluate_default_scope do
         | 
| 149 | 
            -
                            default_scopes.inject(relation) do | | 
| 149 | 
            +
                            default_scopes.inject(relation) do |combined_scope, scope_obj|
         | 
| 150 150 | 
             
                              if execute_scope?(all_queries, scope_obj)
         | 
| 151 151 | 
             
                                scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
         | 
| 152 152 |  | 
| 153 | 
            -
                                 | 
| 153 | 
            +
                                combined_scope.instance_exec(&scope) || combined_scope
         | 
| 154 | 
            +
                              else
         | 
| 155 | 
            +
                                combined_scope
         | 
| 154 156 | 
             
                              end
         | 
| 155 157 | 
             
                            end
         | 
| 156 158 | 
             
                          end
         | 
| @@ -97,7 +97,7 @@ module ActiveRecord | |
| 97 97 |  | 
| 98 98 | 
             
                # Returns a signed id that's generated using a preconfigured +ActiveSupport::MessageVerifier+ instance.
         | 
| 99 99 | 
             
                # This signed id is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
         | 
| 100 | 
            -
                # It can  | 
| 100 | 
            +
                # It can furthermore be set to expire (the default is not to expire), and scoped down with a specific purpose.
         | 
| 101 101 | 
             
                # If the expiration date has been exceeded before +find_signed+ is called, the id won't find the designated
         | 
| 102 102 | 
             
                # record. If a purpose is set, this too must match.
         | 
| 103 103 | 
             
                #
         | 
    
        data/lib/active_record/store.rb
    CHANGED
    
    | @@ -59,7 +59,7 @@ module ActiveRecord | |
| 59 59 | 
             
              #   u.color = 'green'
         | 
| 60 60 | 
             
              #   u.color_changed? # => true
         | 
| 61 61 | 
             
              #   u.color_was # => 'black'
         | 
| 62 | 
            -
              #   u.color_change # => ['black', ' | 
| 62 | 
            +
              #   u.color_change # => ['black', 'green']
         | 
| 63 63 | 
             
              #
         | 
| 64 64 | 
             
              #   # Add additional accessors to an existing store through store_accessor
         | 
| 65 65 | 
             
              #   class SuperUser < User
         | 
| @@ -268,7 +268,7 @@ module ActiveRecord | |
| 268 268 | 
             
                    end
         | 
| 269 269 |  | 
| 270 270 | 
             
                    def dump(obj)
         | 
| 271 | 
            -
                      @coder.dump  | 
| 271 | 
            +
                      @coder.dump as_regular_hash(obj)
         | 
| 272 272 | 
             
                    end
         | 
| 273 273 |  | 
| 274 274 | 
             
                    def load(yaml)
         | 
| @@ -285,6 +285,11 @@ module ActiveRecord | |
| 285 285 | 
             
                        ActiveSupport::HashWithIndifferentAccess.new
         | 
| 286 286 | 
             
                      end
         | 
| 287 287 | 
             
                    end
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                    private
         | 
| 290 | 
            +
                      def as_regular_hash(obj)
         | 
| 291 | 
            +
                        obj.respond_to?(:to_hash) ? obj.to_hash : {}
         | 
| 292 | 
            +
                      end
         | 
| 288 293 | 
             
                  end
         | 
| 289 294 | 
             
              end
         | 
| 290 295 | 
             
            end
         | 
| @@ -137,7 +137,7 @@ module ActiveRecord | |
| 137 137 | 
             
                    @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
         | 
| 138 138 | 
             
                      spec_name = payload[:spec_name] if payload.key?(:spec_name)
         | 
| 139 139 | 
             
                      shard = payload[:shard] if payload.key?(:shard)
         | 
| 140 | 
            -
                      setup_shared_connection_pool
         | 
| 140 | 
            +
                      setup_shared_connection_pool if ActiveRecord.legacy_connection_handling
         | 
| 141 141 |  | 
| 142 142 | 
             
                      if spec_name
         | 
| 143 143 | 
             
                        begin
         | 
| @@ -146,10 +146,14 @@ module ActiveRecord | |
| 146 146 | 
             
                          connection = nil
         | 
| 147 147 | 
             
                        end
         | 
| 148 148 |  | 
| 149 | 
            -
                        if connection | 
| 150 | 
            -
                           | 
| 151 | 
            -
             | 
| 152 | 
            -
                           | 
| 149 | 
            +
                        if connection
         | 
| 150 | 
            +
                          setup_shared_connection_pool unless ActiveRecord.legacy_connection_handling
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                          if !@fixture_connections.include?(connection)
         | 
| 153 | 
            +
                            connection.begin_transaction joinable: false, _lazy: false
         | 
| 154 | 
            +
                            connection.pool.lock_thread = true if lock_threads
         | 
| 155 | 
            +
                            @fixture_connections << connection
         | 
| 156 | 
            +
                          end
         | 
| 153 157 | 
             
                        end
         | 
| 154 158 | 
             
                      end
         | 
| 155 159 | 
             
                    end
         | 
    
        data/lib/active_record.rb
    CHANGED
    
    | @@ -347,12 +347,20 @@ module ActiveRecord | |
| 347 347 | 
             
              singleton_class.attr_accessor :use_yaml_unsafe_load
         | 
| 348 348 | 
             
              self.use_yaml_unsafe_load = false
         | 
| 349 349 |  | 
| 350 | 
            +
              ##
         | 
| 351 | 
            +
              # :singleton-method:
         | 
| 352 | 
            +
              # Application configurable boolean that denotes whether or not to raise
         | 
| 353 | 
            +
              # an exception when the PostgreSQLAdapter is provided with an integer that
         | 
| 354 | 
            +
              # is wider than signed 64bit representation
         | 
| 355 | 
            +
              singleton_class.attr_accessor :raise_int_wider_than_64bit
         | 
| 356 | 
            +
              self.raise_int_wider_than_64bit = true
         | 
| 357 | 
            +
             | 
| 350 358 | 
             
              ##
         | 
| 351 359 | 
             
              # :singleton-method:
         | 
| 352 360 | 
             
              # Application configurable array that provides additional permitted classes
         | 
| 353 361 | 
             
              # to Psych safe_load in the YAML Coder
         | 
| 354 362 | 
             
              singleton_class.attr_accessor :yaml_column_permitted_classes
         | 
| 355 | 
            -
              self.yaml_column_permitted_classes = []
         | 
| 363 | 
            +
              self.yaml_column_permitted_classes = [Symbol]
         | 
| 356 364 |  | 
| 357 365 | 
             
              def self.eager_load!
         | 
| 358 366 | 
             
                super
         | 
    
        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.0. | 
| 4 | 
            +
              version: 7.0.4.1
         | 
| 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:  | 
| 11 | 
            +
            date: 2023-01-17 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.0. | 
| 19 | 
            +
                    version: 7.0.4.1
         | 
| 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.0. | 
| 26 | 
            +
                    version: 7.0.4.1
         | 
| 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.0. | 
| 33 | 
            +
                    version: 7.0.4.1
         | 
| 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.0. | 
| 40 | 
            +
                    version: 7.0.4.1
         | 
| 41 41 | 
             
            description: Databases on Rails. Build a persistent domain model by mapping database
         | 
| 42 42 | 
             
              tables to Ruby classes. Strong conventions for associations, validations, aggregations,
         | 
| 43 43 | 
             
              migrations, and testing come baked-in.
         | 
| @@ -434,10 +434,10 @@ licenses: | |
| 434 434 | 
             
            - MIT
         | 
| 435 435 | 
             
            metadata:
         | 
| 436 436 | 
             
              bug_tracker_uri: https://github.com/rails/rails/issues
         | 
| 437 | 
            -
              changelog_uri: https://github.com/rails/rails/blob/v7.0. | 
| 438 | 
            -
              documentation_uri: https://api.rubyonrails.org/v7.0. | 
| 437 | 
            +
              changelog_uri: https://github.com/rails/rails/blob/v7.0.4.1/activerecord/CHANGELOG.md
         | 
| 438 | 
            +
              documentation_uri: https://api.rubyonrails.org/v7.0.4.1/
         | 
| 439 439 | 
             
              mailing_list_uri: https://discuss.rubyonrails.org/c/rubyonrails-talk
         | 
| 440 | 
            -
              source_code_uri: https://github.com/rails/rails/tree/v7.0. | 
| 440 | 
            +
              source_code_uri: https://github.com/rails/rails/tree/v7.0.4.1/activerecord
         | 
| 441 441 | 
             
              rubygems_mfa_required: 'true'
         | 
| 442 442 | 
             
            post_install_message:
         | 
| 443 443 | 
             
            rdoc_options:
         | 
| @@ -456,7 +456,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 456 456 | 
             
                - !ruby/object:Gem::Version
         | 
| 457 457 | 
             
                  version: '0'
         | 
| 458 458 | 
             
            requirements: []
         | 
| 459 | 
            -
            rubygems_version: 3. | 
| 459 | 
            +
            rubygems_version: 3.4.3
         | 
| 460 460 | 
             
            signing_key:
         | 
| 461 461 | 
             
            specification_version: 4
         | 
| 462 462 | 
             
            summary: Object-relational mapper framework (part of Rails).
         |