activerecord 6.0.0.rc1 → 6.0.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 +39 -0
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/collection_proxy.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_association.rb +11 -2
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_methods.rb +0 -51
- data/lib/active_record/attribute_methods/dirty.rb +6 -1
- data/lib/active_record/autosave_association.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +93 -11
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +53 -0
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +8 -7
- data/lib/active_record/connection_adapters/abstract/transaction.rb +12 -4
- data/lib/active_record/connection_adapters/abstract_adapter.rb +40 -20
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +3 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +10 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +39 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +8 -1
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +38 -2
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +12 -2
- data/lib/active_record/connection_handling.rb +6 -2
- data/lib/active_record/database_configurations.rb +6 -6
- data/lib/active_record/gem_version.rb +1 -1
- data/lib/active_record/middleware/database_selector.rb +3 -3
- data/lib/active_record/middleware/database_selector/resolver.rb +2 -2
- data/lib/active_record/migration.rb +26 -23
- data/lib/active_record/railtie.rb +0 -1
- data/lib/active_record/railties/databases.rake +57 -23
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/relation/calculations.rb +1 -1
- data/lib/active_record/relation/finder_methods.rb +4 -2
- data/lib/active_record/relation/merger.rb +6 -2
- data/lib/active_record/relation/query_methods.rb +32 -32
- data/lib/active_record/sanitization.rb +30 -2
- data/lib/active_record/schema.rb +1 -1
- data/lib/active_record/schema_dumper.rb +5 -1
- data/lib/active_record/table_metadata.rb +6 -10
- data/lib/active_record/tasks/database_tasks.rb +41 -8
- data/lib/active_record/tasks/mysql_database_tasks.rb +3 -1
- data/lib/active_record/timestamp.rb +26 -16
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +9 -10
- data/lib/active_record/type_caster/connection.rb +16 -10
- data/lib/arel/visitors/depth_first.rb +1 -1
- data/lib/arel/visitors/to_sql.rb +23 -26
- data/lib/arel/visitors/visitor.rb +9 -5
- metadata +8 -8
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 97bc72165e9eb1685576780f439be5be8894b7c589cc890d8c6340b8125de0a4
         | 
| 4 | 
            +
              data.tar.gz: 74d58cd2f64976ef8faa42a02e94e6d9c9356fce3f0f2c219f7377a09712e7a4
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 5306d17e736a64c87fc0115299b055c58343df4d18a53d532b09e570d6cc799abf84b4149deef9c03f56563ed23ee563cf57d03fc6c65529e9a6aa0324ca1614
         | 
| 7 | 
            +
              data.tar.gz: 6fe8094ad7c0d0433c23691e372417124bddf17659c4bcb64b0bca5af0513d2c9b8599cfe0c244d28649529ab64b99c4a74b638bdf5ab9b4932c276a287d1e78
         | 
    
        data/CHANGELOG.md
    CHANGED
    
    | @@ -1,3 +1,42 @@ | |
| 1 | 
            +
            ## Rails 6.0.0.rc2 (July 22, 2019) ##
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            *   Add database_exists? method to connection adapters to check if a database exists.
         | 
| 4 | 
            +
             | 
| 5 | 
            +
                *Guilherme Mansur*
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            *   PostgreSQL: Fix GROUP BY with ORDER BY virtual count attribute.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                Fixes #36022.
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                *Ryuta Kamizono*
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            *   Make ActiveRecord `ConnectionPool.connections` method thread-safe.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                Fixes #36465.
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                *Jeff Doering*
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            *   Fix sqlite3 collation parsing when using decimal columns.
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                *Martin R. Schuster*
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            *   Fix invalid schema when primary key column has a comment.
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                Fixes #29966.
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                *Guilherme Goettems Schneider*
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            *   Fix table comment also being applied to the primary key column.
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                *Guilherme Goettems Schneider*
         | 
| 32 | 
            +
             | 
| 33 | 
            +
            *   Fix merging left_joins to maintain its own `join_type` context.
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                Fixes #36103.
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                *Ryuta Kamizono*
         | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 1 40 | 
             
            ## Rails 6.0.0.rc1 (April 24, 2019) ##
         | 
| 2 41 |  | 
| 3 42 | 
             
            *   Add `touch` option to `has_one` association.
         | 
| @@ -22,9 +22,9 @@ module ActiveRecord::Associations::Builder # :nodoc: | |
| 22 22 |  | 
| 23 23 | 
             
                def self.define_extensions(model, name, &block)
         | 
| 24 24 | 
             
                  if block_given?
         | 
| 25 | 
            -
                    extension_module_name = "#{ | 
| 25 | 
            +
                    extension_module_name = "#{name.to_s.camelize}AssociationExtension"
         | 
| 26 26 | 
             
                    extension = Module.new(&block)
         | 
| 27 | 
            -
                    model. | 
| 27 | 
            +
                    model.const_set(extension_module_name, extension)
         | 
| 28 28 | 
             
                  end
         | 
| 29 29 | 
             
                end
         | 
| 30 30 |  | 
| @@ -1029,7 +1029,7 @@ module ActiveRecord | |
| 1029 1029 | 
             
                  alias_method :append, :<<
         | 
| 1030 1030 | 
             
                  alias_method :concat, :<<
         | 
| 1031 1031 |  | 
| 1032 | 
            -
                  def prepend(*args)
         | 
| 1032 | 
            +
                  def prepend(*args) # :nodoc:
         | 
| 1033 1033 | 
             
                    raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
         | 
| 1034 1034 | 
             
                  end
         | 
| 1035 1035 |  | 
| @@ -64,16 +64,17 @@ module ActiveRecord | |
| 64 64 | 
             
                    end
         | 
| 65 65 | 
             
                  end
         | 
| 66 66 |  | 
| 67 | 
            -
                  def initialize(base, table, associations)
         | 
| 67 | 
            +
                  def initialize(base, table, associations, join_type)
         | 
| 68 68 | 
             
                    tree = self.class.make_tree associations
         | 
| 69 69 | 
             
                    @join_root = JoinBase.new(base, table, build(tree, base))
         | 
| 70 | 
            +
                    @join_type = join_type
         | 
| 70 71 | 
             
                  end
         | 
| 71 72 |  | 
| 72 73 | 
             
                  def reflections
         | 
| 73 74 | 
             
                    join_root.drop(1).map!(&:reflection)
         | 
| 74 75 | 
             
                  end
         | 
| 75 76 |  | 
| 76 | 
            -
                  def join_constraints(joins_to_add,  | 
| 77 | 
            +
                  def join_constraints(joins_to_add, alias_tracker)
         | 
| 77 78 | 
             
                    @alias_tracker = alias_tracker
         | 
| 78 79 |  | 
| 79 80 | 
             
                    construct_tables!(join_root)
         | 
| @@ -82,9 +83,9 @@ module ActiveRecord | |
| 82 83 | 
             
                    joins.concat joins_to_add.flat_map { |oj|
         | 
| 83 84 | 
             
                      construct_tables!(oj.join_root)
         | 
| 84 85 | 
             
                      if join_root.match? oj.join_root
         | 
| 85 | 
            -
                        walk join_root, oj. | 
| 86 | 
            +
                        walk(join_root, oj.join_root, oj.join_type)
         | 
| 86 87 | 
             
                      else
         | 
| 87 | 
            -
                        make_join_constraints(oj.join_root, join_type)
         | 
| 88 | 
            +
                        make_join_constraints(oj.join_root, oj.join_type)
         | 
| 88 89 | 
             
                      end
         | 
| 89 90 | 
             
                    }
         | 
| 90 91 | 
             
                  end
         | 
| @@ -125,7 +126,7 @@ module ActiveRecord | |
| 125 126 | 
             
                  end
         | 
| 126 127 |  | 
| 127 128 | 
             
                  protected
         | 
| 128 | 
            -
                    attr_reader :join_root
         | 
| 129 | 
            +
                    attr_reader :join_root, :join_type
         | 
| 129 130 |  | 
| 130 131 | 
             
                  private
         | 
| 131 132 | 
             
                    attr_reader :alias_tracker
         | 
| @@ -151,7 +152,7 @@ module ActiveRecord | |
| 151 152 | 
             
                      end
         | 
| 152 153 | 
             
                    end
         | 
| 153 154 |  | 
| 154 | 
            -
                    def make_constraints(parent, child, join_type | 
| 155 | 
            +
                    def make_constraints(parent, child, join_type)
         | 
| 155 156 | 
             
                      foreign_table = parent.table
         | 
| 156 157 | 
             
                      foreign_klass = parent.base_klass
         | 
| 157 158 | 
             
                      joins = child.join_constraints(foreign_table, foreign_klass, join_type, alias_tracker)
         | 
| @@ -173,13 +174,13 @@ module ActiveRecord | |
| 173 174 | 
             
                      join ? "#{name}_join" : name
         | 
| 174 175 | 
             
                    end
         | 
| 175 176 |  | 
| 176 | 
            -
                    def walk(left, right)
         | 
| 177 | 
            +
                    def walk(left, right, join_type)
         | 
| 177 178 | 
             
                      intersection, missing = right.children.map { |node1|
         | 
| 178 179 | 
             
                        [left.children.find { |node2| node1.match? node2 }, node1]
         | 
| 179 180 | 
             
                      }.partition(&:first)
         | 
| 180 181 |  | 
| 181 | 
            -
                      joins = intersection.flat_map { |l, r| r.table = l.table; walk(l, r) }
         | 
| 182 | 
            -
                      joins.concat missing.flat_map { |_, n| make_constraints(left, n) }
         | 
| 182 | 
            +
                      joins = intersection.flat_map { |l, r| r.table = l.table; walk(l, r, join_type) }
         | 
| 183 | 
            +
                      joins.concat missing.flat_map { |_, n| make_constraints(left, n, join_type) }
         | 
| 183 184 | 
             
                    end
         | 
| 184 185 |  | 
| 185 186 | 
             
                    def find_reflection(klass, name)
         | 
| @@ -44,8 +44,7 @@ module ActiveRecord | |
| 44 44 |  | 
| 45 45 | 
             
                        unless others.empty?
         | 
| 46 46 | 
             
                          joins.concat arel.join_sources
         | 
| 47 | 
            -
                           | 
| 48 | 
            -
                          right.expr.children.concat(others)
         | 
| 47 | 
            +
                          append_constraints(joins.last, others)
         | 
| 49 48 | 
             
                        end
         | 
| 50 49 |  | 
| 51 50 | 
             
                        # The current table in this iteration becomes the foreign table in the next
         | 
| @@ -65,6 +64,16 @@ module ActiveRecord | |
| 65 64 |  | 
| 66 65 | 
             
                      @readonly = reflection.scope && reflection.scope_for(base_klass.unscoped).readonly_value
         | 
| 67 66 | 
             
                    end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
                    private
         | 
| 69 | 
            +
                      def append_constraints(join, constraints)
         | 
| 70 | 
            +
                        if join.is_a?(Arel::Nodes::StringJoin)
         | 
| 71 | 
            +
                          join_string = table.create_and(constraints.unshift(join.left))
         | 
| 72 | 
            +
                          join.left = Arel.sql(base_klass.connection.visitor.compile(join_string))
         | 
| 73 | 
            +
                        else
         | 
| 74 | 
            +
                          join.right.expr.children.concat(constraints)
         | 
| 75 | 
            +
                        end
         | 
| 76 | 
            +
                      end
         | 
| 68 77 | 
             
                  end
         | 
| 69 78 | 
             
                end
         | 
| 70 79 | 
             
              end
         | 
| @@ -27,7 +27,9 @@ module ActiveRecord | |
| 27 27 | 
             
                    end
         | 
| 28 28 |  | 
| 29 29 | 
             
                    def records_by_owner
         | 
| 30 | 
            -
                       | 
| 30 | 
            +
                      # owners can be duplicated when a relation has a collection association join
         | 
| 31 | 
            +
                      # #compare_by_identity makes such owners different hash keys
         | 
| 32 | 
            +
                      @records_by_owner ||= preloaded_records.each_with_object({}.compare_by_identity) do |record, result|
         | 
| 31 33 | 
             
                        owners_by_key[convert_key(record[association_key_name])].each do |owner|
         | 
| 32 34 | 
             
                          (result[owner] ||= []) << record
         | 
| 33 35 | 
             
                        end
         | 
| @@ -159,57 +159,6 @@ module ActiveRecord | |
| 159 159 | 
             
                    end
         | 
| 160 160 | 
             
                  end
         | 
| 161 161 |  | 
| 162 | 
            -
                  # Regexp for column names (with or without a table name prefix). Matches
         | 
| 163 | 
            -
                  # the following:
         | 
| 164 | 
            -
                  #   "#{table_name}.#{column_name}"
         | 
| 165 | 
            -
                  #   "#{column_name}"
         | 
| 166 | 
            -
                  COLUMN_NAME = /\A(?:\w+\.)?\w+\z/i
         | 
| 167 | 
            -
             | 
| 168 | 
            -
                  # Regexp for column names with order (with or without a table name
         | 
| 169 | 
            -
                  # prefix, with or without various order modifiers). Matches the following:
         | 
| 170 | 
            -
                  #   "#{table_name}.#{column_name}"
         | 
| 171 | 
            -
                  #   "#{table_name}.#{column_name} #{direction}"
         | 
| 172 | 
            -
                  #   "#{table_name}.#{column_name} #{direction} NULLS FIRST"
         | 
| 173 | 
            -
                  #   "#{table_name}.#{column_name} NULLS LAST"
         | 
| 174 | 
            -
                  #   "#{column_name}"
         | 
| 175 | 
            -
                  #   "#{column_name} #{direction}"
         | 
| 176 | 
            -
                  #   "#{column_name} #{direction} NULLS FIRST"
         | 
| 177 | 
            -
                  #   "#{column_name} NULLS LAST"
         | 
| 178 | 
            -
                  COLUMN_NAME_WITH_ORDER = /
         | 
| 179 | 
            -
                    \A
         | 
| 180 | 
            -
                    (?:\w+\.)?
         | 
| 181 | 
            -
                    \w+
         | 
| 182 | 
            -
                    (?:\s+asc|\s+desc)?
         | 
| 183 | 
            -
                    (?:\s+nulls\s+(?:first|last))?
         | 
| 184 | 
            -
                    \z
         | 
| 185 | 
            -
                  /ix
         | 
| 186 | 
            -
             | 
| 187 | 
            -
                  def disallow_raw_sql!(args, permit: COLUMN_NAME) # :nodoc:
         | 
| 188 | 
            -
                    unexpected = args.reject do |arg|
         | 
| 189 | 
            -
                      Arel.arel_node?(arg) ||
         | 
| 190 | 
            -
                        arg.to_s.split(/\s*,\s*/).all? { |part| permit.match?(part) }
         | 
| 191 | 
            -
                    end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
                    return if unexpected.none?
         | 
| 194 | 
            -
             | 
| 195 | 
            -
                    if allow_unsafe_raw_sql == :deprecated
         | 
| 196 | 
            -
                      ActiveSupport::Deprecation.warn(
         | 
| 197 | 
            -
                        "Dangerous query method (method whose arguments are used as raw " \
         | 
| 198 | 
            -
                        "SQL) called with non-attribute argument(s): " \
         | 
| 199 | 
            -
                        "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
         | 
| 200 | 
            -
                        "arguments will be disallowed in Rails 6.1. This method should " \
         | 
| 201 | 
            -
                        "not be called with user-provided values, such as request " \
         | 
| 202 | 
            -
                        "parameters or model attributes. Known-safe values can be passed " \
         | 
| 203 | 
            -
                        "by wrapping them in Arel.sql()."
         | 
| 204 | 
            -
                      )
         | 
| 205 | 
            -
                    else
         | 
| 206 | 
            -
                      raise(ActiveRecord::UnknownAttributeReference,
         | 
| 207 | 
            -
                        "Query method called with non-attribute argument(s): " +
         | 
| 208 | 
            -
                        unexpected.map(&:inspect).join(", ")
         | 
| 209 | 
            -
                      )
         | 
| 210 | 
            -
                    end
         | 
| 211 | 
            -
                  end
         | 
| 212 | 
            -
             | 
| 213 162 | 
             
                  # Returns true if the given attribute exists, otherwise false.
         | 
| 214 163 | 
             
                  #
         | 
| 215 164 | 
             
                  #   class Person < ActiveRecord::Base
         | 
| @@ -177,6 +177,11 @@ module ActiveRecord | |
| 177 177 |  | 
| 178 178 | 
             
                      affected_rows = super
         | 
| 179 179 |  | 
| 180 | 
            +
                      if @_skip_dirty_tracking ||= false
         | 
| 181 | 
            +
                        clear_attribute_changes(@_touch_attr_names)
         | 
| 182 | 
            +
                        return affected_rows
         | 
| 183 | 
            +
                      end
         | 
| 184 | 
            +
             | 
| 180 185 | 
             
                      changes = {}
         | 
| 181 186 | 
             
                      @attributes.keys.each do |attr_name|
         | 
| 182 187 | 
             
                        next if @_touch_attr_names.include?(attr_name)
         | 
| @@ -193,7 +198,7 @@ module ActiveRecord | |
| 193 198 |  | 
| 194 199 | 
             
                      affected_rows
         | 
| 195 200 | 
             
                    ensure
         | 
| 196 | 
            -
                      @_touch_attr_names = nil
         | 
| 201 | 
            +
                      @_touch_attr_names, @_skip_dirty_tracking = nil, nil
         | 
| 197 202 | 
             
                    end
         | 
| 198 203 |  | 
| 199 204 | 
             
                    def _update_record(attribute_names = attribute_names_for_partial_writes)
         | 
| @@ -3,6 +3,7 @@ | |
| 3 3 | 
             
            require "thread"
         | 
| 4 4 | 
             
            require "concurrent/map"
         | 
| 5 5 | 
             
            require "monitor"
         | 
| 6 | 
            +
            require "weakref"
         | 
| 6 7 |  | 
| 7 8 | 
             
            module ActiveRecord
         | 
| 8 9 | 
             
              # Raised when a connection could not be obtained within the connection
         | 
| @@ -19,6 +20,26 @@ module ActiveRecord | |
| 19 20 | 
             
              end
         | 
| 20 21 |  | 
| 21 22 | 
             
              module ConnectionAdapters
         | 
| 23 | 
            +
                module AbstractPool # :nodoc:
         | 
| 24 | 
            +
                  def get_schema_cache(connection)
         | 
| 25 | 
            +
                    @schema_cache ||= SchemaCache.new(connection)
         | 
| 26 | 
            +
                    @schema_cache.connection = connection
         | 
| 27 | 
            +
                    @schema_cache
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  def set_schema_cache(cache)
         | 
| 31 | 
            +
                    @schema_cache = cache
         | 
| 32 | 
            +
                  end
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                class NullPool # :nodoc:
         | 
| 36 | 
            +
                  include ConnectionAdapters::AbstractPool
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  def initialize
         | 
| 39 | 
            +
                    @schema_cache = nil
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 22 43 | 
             
                # Connection pool base class for managing Active Record database
         | 
| 23 44 | 
             
                # connections.
         | 
| 24 45 | 
             
                #
         | 
| @@ -294,23 +315,51 @@ module ActiveRecord | |
| 294 315 | 
             
                      @frequency = frequency
         | 
| 295 316 | 
             
                    end
         | 
| 296 317 |  | 
| 318 | 
            +
                    @mutex = Mutex.new
         | 
| 319 | 
            +
                    @pools = {}
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                    class << self
         | 
| 322 | 
            +
                      def register_pool(pool, frequency) # :nodoc:
         | 
| 323 | 
            +
                        @mutex.synchronize do
         | 
| 324 | 
            +
                          unless @pools.key?(frequency)
         | 
| 325 | 
            +
                            @pools[frequency] = []
         | 
| 326 | 
            +
                            spawn_thread(frequency)
         | 
| 327 | 
            +
                          end
         | 
| 328 | 
            +
                          @pools[frequency] << WeakRef.new(pool)
         | 
| 329 | 
            +
                        end
         | 
| 330 | 
            +
                      end
         | 
| 331 | 
            +
             | 
| 332 | 
            +
                      private
         | 
| 333 | 
            +
             | 
| 334 | 
            +
                        def spawn_thread(frequency)
         | 
| 335 | 
            +
                          Thread.new(frequency) do |t|
         | 
| 336 | 
            +
                            loop do
         | 
| 337 | 
            +
                              sleep t
         | 
| 338 | 
            +
                              @mutex.synchronize do
         | 
| 339 | 
            +
                                @pools[frequency].select!(&:weakref_alive?)
         | 
| 340 | 
            +
                                @pools[frequency].each do |p|
         | 
| 341 | 
            +
                                  p.reap
         | 
| 342 | 
            +
                                  p.flush
         | 
| 343 | 
            +
                                rescue WeakRef::RefError
         | 
| 344 | 
            +
                                end
         | 
| 345 | 
            +
                              end
         | 
| 346 | 
            +
                            end
         | 
| 347 | 
            +
                          end
         | 
| 348 | 
            +
                        end
         | 
| 349 | 
            +
                    end
         | 
| 350 | 
            +
             | 
| 297 351 | 
             
                    def run
         | 
| 298 352 | 
             
                      return unless frequency && frequency > 0
         | 
| 299 | 
            -
                       | 
| 300 | 
            -
                        loop do
         | 
| 301 | 
            -
                          sleep t
         | 
| 302 | 
            -
                          p.reap
         | 
| 303 | 
            -
                          p.flush
         | 
| 304 | 
            -
                        end
         | 
| 305 | 
            -
                      }
         | 
| 353 | 
            +
                      self.class.register_pool(pool, frequency)
         | 
| 306 354 | 
             
                    end
         | 
| 307 355 | 
             
                  end
         | 
| 308 356 |  | 
| 309 357 | 
             
                  include MonitorMixin
         | 
| 310 358 | 
             
                  include QueryCache::ConnectionPoolConfiguration
         | 
| 359 | 
            +
                  include ConnectionAdapters::AbstractPool
         | 
| 311 360 |  | 
| 312 361 | 
             
                  attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache
         | 
| 313 | 
            -
                  attr_reader :spec, : | 
| 362 | 
            +
                  attr_reader :spec, :size, :reaper
         | 
| 314 363 |  | 
| 315 364 | 
             
                  # Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
         | 
| 316 365 | 
             
                  # object which describes database connection information (e.g. adapter,
         | 
| @@ -379,7 +428,7 @@ module ActiveRecord | |
| 379 428 | 
             
                  # #connection can be called any number of times; the connection is
         | 
| 380 429 | 
             
                  # held in a cache keyed by a thread.
         | 
| 381 430 | 
             
                  def connection
         | 
| 382 | 
            -
                    @thread_cached_conns[connection_cache_key( | 
| 431 | 
            +
                    @thread_cached_conns[connection_cache_key(current_thread)] ||= checkout
         | 
| 383 432 | 
             
                  end
         | 
| 384 433 |  | 
| 385 434 | 
             
                  # Returns true if there is an open connection being used for the current thread.
         | 
| @@ -388,7 +437,7 @@ module ActiveRecord | |
| 388 437 | 
             
                  # #connection or #with_connection methods. Connections obtained through
         | 
| 389 438 | 
             
                  # #checkout will not be detected by #active_connection?
         | 
| 390 439 | 
             
                  def active_connection?
         | 
| 391 | 
            -
                    @thread_cached_conns[connection_cache_key( | 
| 440 | 
            +
                    @thread_cached_conns[connection_cache_key(current_thread)]
         | 
| 392 441 | 
             
                  end
         | 
| 393 442 |  | 
| 394 443 | 
             
                  # Signal that the thread is finished with the current connection.
         | 
| @@ -423,6 +472,21 @@ module ActiveRecord | |
| 423 472 | 
             
                    synchronize { @connections.any? }
         | 
| 424 473 | 
             
                  end
         | 
| 425 474 |  | 
| 475 | 
            +
                  # Returns an array containing the connections currently in the pool.
         | 
| 476 | 
            +
                  # Access to the array does not require synchronization on the pool because
         | 
| 477 | 
            +
                  # the array is newly created and not retained by the pool.
         | 
| 478 | 
            +
                  #
         | 
| 479 | 
            +
                  # However; this method bypasses the ConnectionPool's thread-safe connection
         | 
| 480 | 
            +
                  # access pattern. A returned connection may be owned by another thread,
         | 
| 481 | 
            +
                  # unowned, or by happen-stance owned by the calling thread.
         | 
| 482 | 
            +
                  #
         | 
| 483 | 
            +
                  # Calling methods on a connection without ownership is subject to the
         | 
| 484 | 
            +
                  # thread-safety guarantees of the underlying method. Many of the methods
         | 
| 485 | 
            +
                  # on connection adapter classes are inherently multi-thread unsafe.
         | 
| 486 | 
            +
                  def connections
         | 
| 487 | 
            +
                    synchronize { @connections.dup }
         | 
| 488 | 
            +
                  end
         | 
| 489 | 
            +
             | 
| 426 490 | 
             
                  # Disconnects all connections in the pool, and clears the pool.
         | 
| 427 491 | 
             
                  #
         | 
| 428 492 | 
             
                  # Raises:
         | 
| @@ -668,6 +732,10 @@ module ActiveRecord | |
| 668 732 | 
             
                      thread
         | 
| 669 733 | 
             
                    end
         | 
| 670 734 |  | 
| 735 | 
            +
                    def current_thread
         | 
| 736 | 
            +
                      @lock_thread || Thread.current
         | 
| 737 | 
            +
                    end
         | 
| 738 | 
            +
             | 
| 671 739 | 
             
                    # Take control of all existing connections so a "group" action such as
         | 
| 672 740 | 
             
                    # reload/disconnect can be performed safely. It is no longer enough to
         | 
| 673 741 | 
             
                    # wrap it in +synchronize+ because some pool's actions are allowed
         | 
| @@ -809,7 +877,6 @@ module ActiveRecord | |
| 809 877 |  | 
| 810 878 | 
             
                    def new_connection
         | 
| 811 879 | 
             
                      Base.send(spec.adapter_method, spec.config).tap do |conn|
         | 
| 812 | 
            -
                        conn.schema_cache = schema_cache.dup if schema_cache
         | 
| 813 880 | 
             
                        conn.check_version
         | 
| 814 881 | 
             
                      end
         | 
| 815 882 | 
             
                    end
         | 
| @@ -938,15 +1005,30 @@ module ActiveRecord | |
| 938 1005 | 
             
                    end
         | 
| 939 1006 | 
             
                  end
         | 
| 940 1007 |  | 
| 1008 | 
            +
                  attr_reader :prevent_writes
         | 
| 1009 | 
            +
             | 
| 941 1010 | 
             
                  def initialize
         | 
| 942 1011 | 
             
                    # These caches are keyed by spec.name (ConnectionSpecification#name).
         | 
| 943 1012 | 
             
                    @owner_to_pool = ConnectionHandler.create_owner_to_pool
         | 
| 1013 | 
            +
                    @prevent_writes = false
         | 
| 944 1014 |  | 
| 945 1015 | 
             
                    # Backup finalizer: if the forked child never needed a pool, the above
         | 
| 946 1016 | 
             
                    # early discard has not occurred
         | 
| 947 1017 | 
             
                    ObjectSpace.define_finalizer self, ConnectionHandler.unowned_pool_finalizer(@owner_to_pool)
         | 
| 948 1018 | 
             
                  end
         | 
| 949 1019 |  | 
| 1020 | 
            +
                  # Prevent writing to the database regardless of role.
         | 
| 1021 | 
            +
                  #
         | 
| 1022 | 
            +
                  # In some cases you may want to prevent writes to the database
         | 
| 1023 | 
            +
                  # even if you are on a database that can write. `while_preventing_writes`
         | 
| 1024 | 
            +
                  # will prevent writes to the database for the duration of the block.
         | 
| 1025 | 
            +
                  def while_preventing_writes
         | 
| 1026 | 
            +
                    original, @prevent_writes = @prevent_writes, true
         | 
| 1027 | 
            +
                    yield
         | 
| 1028 | 
            +
                  ensure
         | 
| 1029 | 
            +
                    @prevent_writes = original
         | 
| 1030 | 
            +
                  end
         | 
| 1031 | 
            +
             | 
| 950 1032 | 
             
                  def connection_pool_list
         | 
| 951 1033 | 
             
                    owner_to_pool.values.compact
         | 
| 952 1034 | 
             
                  end
         |