The previous: config option was being skipped because it was checking
the existence of a reader method instead of the accessor itself.
This also adds a test for the .configure option that was missing.
Before when calling `preventing_writes?` in the connection the code
would raise a `NoMethodError` when calling `current_preventing_writes`
in a String.
This problem only happen when `establish_connection` is called on the
`ConnectionHandler` and not in the model itself.
This also removes the conditional from the `PoolConfig`.
The payload name for `delete_all` was named "Destroy" in #30619 since
`delete_all` was used in `record.destroy` at that time.
Since ea45d56, `record.destroy` no longer relies on `delete_all`, so now
we can improve the payload name for `delete_all` to more appropriate.
If a model which has a user-defined `self.default_scope` is joined with
table alias, a user-defined `self.default_scope` ignores table alias.
This problem has potentially existed for a long time, but it has not
become apparent because it is difficult to meet this condition.
Since #40106, table alias is easily used if association names are used
in `where`.
So user-defined `self.default_scope` should be evaluated in the current
aliased relation.
Fixes#41857.
This commit adds more empty methods to a connection pool.
In normal usage, a connection is always be associated with a pool, but
for testing (we do this a few places in the AR test suite) it can be
convenient to build a connection and use it without associating a pool.
In most cases, this worked fine, but there were a few corner cases which
would hit NoMethodError on the NullPool. In particular in some cases
raising in a transaction would error in connection.throw_away!.
To make these "standalone" or "pool-less" connections work consistently,
this commit adds the methods which a connection could call on it's pool
(but not any other of ConnectionPool's public interface).
This deprecates `legacy_connection_handling` via the
`connection_handlers` setter. This is called from the ActiveRecord
Railtie on boot and since most applications don't set this themselves
this will prevent the deprecation from being raised multiple times for a
test run or in development.
I've also updated the guides to include a migration path for
applications using the deprecated methods. The majority of applications
won't need to make any changes.
Reusing the "books" one could cause interferences when fixtures are
loaded in a very specific order such as:
https://buildkite.com/rails/rails/builds/76217#ee4ce591-e6c1-4a0d-a7db-1f83647d141e
Reproduction script:
```
activerecord $ bin/test -v --seed 23607 -n "/^(?:EagerAssociationTest#(?:test_preloading_a_regular_association_with_a_typo_through_a_polymorphic_association_still_raises)|ActiveRecord::Encryption::EncryptableFixtureTest#(?:test_fixtures_get_encrypted_automatically)|ViewWithoutPrimaryKeyTest#(?:test_attributes|test_reading))$/"
```
I noticed in profiles of simple queries (like `Post.where(id: 1).first`)
we're spending lots of time looking up the current thread. I couldn't
find any way to speed this up in Ruby, so I thought maybe we could call
`Thread.current` fewer times per query.
This patch should eliminate 4 calls to `Thread.current` per query.
For this benchmark:
```ruby
StackProf.run(mode: :wall, out: 'out.dump') do
8000.times { Post.where(id: id).first }
end
```
`Thread.current` goes from 7% to 4.7% of time:
```
==================================
Mode: wall(1000)
Samples: 1633 (0.00% miss rate)
GC: 51 (3.12%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
140 (8.6%) 140 (8.6%) String#sub!
114 (7.0%) 114 (7.0%) Thread.current
```
```
==================================
Mode: wall(1000)
Samples: 1719 (0.00% miss rate)
GC: 51 (2.97%)
==================================
TOTAL (pct) SAMPLES (pct) FRAME
134 (7.8%) 134 (7.8%) String#sub!
99 (5.8%) 99 (5.8%) Module#===
81 (4.7%) 81 (4.7%) Thread.current
```
This isn't huge, but I think we need to find more sources of
Thread.current. It's surprising to me that we spend so much time
looking up the current thread when doing a query that is so "easy"
We're spending time validating symbol parameters of the ScopeRegistry.
It's an internal class, and we can stop validating symbols by converting
to methods (you'll automatically get an error if you try to call a
method that doesn't exist). Second, since we only have 3 things to keep
track of, rather than keep those things in a hash, just break it out in
to 3 instance variables. (This is absolutely not a memory bottleneck,
but technically this patch will save some memory as the 3 ivars will be
embedded in the object rather than require a full st_table for the
original wrapper hash)
This examines all the association branches we are being asked to preload
and will delay loading an association if it's likely that we find a
similar association later and can batch them together.
For example, when loading
Author.preload(:posts, favorite_authors: :posts).first
The preloader now knows to delay loading the top level posts so that it
can load both the top level :posts and the :posts from the favourite
authors associations together.
Co-authored-by: Dinah Shi <dinahshi@github.com>
This implements several changes to encourage deterministic encryption to
remain unchanged. The main motivation is letting you define unique
indexes on deterministically-encrypted columns:
- By default, deterministic encryption will always use the oldest
encryption scheme to encrypt new data, when there are many.
- You can skip this default behavior and make it always use the current
encryption scheme with:
```ruby
deterministic: { fixed: false } # using this should be a rare need
```
- Deterministic encryption still supports previous encryption schemes
normally. So they will be used to add additional values to queries, for
example.
- You can't rotate deterministic encryption keys anymore. We can add
support for that in the future.
This makes for reasonable defaults:
- People using "deterministic: true" will get unique indexes working out
of the box.
- The system will encourage keeping deterministic encryption stable:
- By always using oldest encryption schemes
- By forbidding configuring multiple keys
But you can still opt-out of the default if you need to.
We are not encrypting attributes when loading models with the table
missing. This way we make sure we only load the encrypted models when
necessary during the encryption tests and prevent the problem of missing
encrypted attributes due to having cached the class without them encrypted.