When `destroy` is called twice on a persisted record inside a
transaction, the after_commit callbacks fail to run. The second
time `destroy` is called, `@_trigger_destroy_callback` is set to false
because the record has already been deleted, even though the
transaction hasn't completed yet, and the after_commit callbacks haven't
had a chance to run from the first `destroy`.
SelectManager#with currently accepts As and TableAlias nodes.
Neither of these support materialization hints for the query
planner. Both Postgres and SQLite support such hints.
This commit adds a Cte node that does support materialization
hints. It continues to support As and TableAlias nodes by
translating them into Cte nodes.
Introduces a new engine initializer, `add_fixture_paths`, which
automatically adds a `test/fixtures` folder under the engine root to
`fixture_paths` if such a folder exists.
The recent [refactor][1] to the MySQL DatabaseStatements classes renamed
Mysql::DatabaseStatements to Mysql2::DatabaseStatements. That commit
also updated most of the references to the top level Mysql2 to be
explicit since Ruby will now assume they refer to
ActiveRecord::ConnectionAdapters::Mysql2. However, Mysql2::Error was not
updated, and that rescue will currently raise:
```
NameError: uninitialized constant ActiveRecord::ConnectionAdapters::Mysql2::Error
```
if the execute raises any error.
To fix this, Mysql2 must be changed to explicitly refer to the top level
namespace.
[1]: 93b5fc1f95e04b6a51f3e8dd2c885ba9ddd139a6
This is basically a multi-db aware version of `ActiveRecord::Base.connection.disconnect!`.
It also avoid connecting to the database if we weren't already.
This can be useful to reset state after `establish_connection` has been used.
This reverts commit 6adaeb864946718f71746958d3463e5c0a266b30, reversing
changes made to a792a62080b82f776ca62bbc85af45ee73fe368e.
We're going to forward fix this in our application rather than keep this
revert in. Reverting other changes has turned out to be too difficult to
get back to a state where our application is retrying queries.
Partially Fixes#48164
Today, connections are discarded in `within_transaction` if rolling back
fails after the call to `yield` raises. This is done to prevent a
connection from being left in a transaction if the rollback actually
failed.
This change causes connections to be discarded in the following
additional cases where the connection may be left in a transaction:
- If beginning the transaction fails.
- If rolling back the transaction fails.
- If committing the transaction fails, then rolling back fails.
This is accomplished by rescuing all exceptions raised in
`within_transaction` and discarding the connection if the transaction
has not been been both initialized and completed.
This reverts commit 663df3aa095cc90b1a2f1616ba472672ea606f73, reversing
changes made to 9b4fff264e035f08b263c189f5899b114c4feadd.
The changes here forced our code through a different codepath,
circumventing the patch on `execute` to retry queries. Since we also
patch `execute` from Semian it's not clear the correct path forward and
we're going to revert for now.
When an Active Record encrypted attribute is declared, a filter for it
is automatically added to `config.filter_parameters`. Prior to this
commit, the filter would be re-added every time the model was reloaded:
```ruby
class Post < ActiveRecord::Base
encrypts :title
end
```
```irb
irb> Rails.application.config.filter_parameters
# => [:passw, ..., :ssn]
irb> Post
irb> Rails.application.config.filter_parameters
# => [:passw, ..., :ssn, "post.title"]
irb> reload!
irb> Post
irb> Rails.application.config.filter_parameters
# => [:passw, ..., :ssn, "post.title", "post.title"]
```
This commit ensures filters are only added once so that
`config.filter_parameters` does not grow unbounded.
In #48106, `Module#deep_dup` was changed to return the module itself
(not a copy) when the module is not anonymous. However, that causes
non-anonymous modules to become frozen via `value.deep_dup.freeze` when
passed to `ActiveModel::Type::Helpers::Mutable#immutable_value`. So,
for example, class attributes can no longer be set on the module.
To prevent such issues, this commit removes the `freeze` from
`immutable_value`. `immutable_value` is only called by
`ActiveRecord::PredicateBuilder#build_bind_attribute`, which only cares
that other code cannot mutate the value, not that the value is actually
frozen.
This PR does the following:
* Adds `trilogy` to lists of adapters where applicable
* Uses `MySQL` instead of adatper names where applicable
* Splits type information into adapters code so that the adapter is set
correctly.
* Fix tests that were using mysql2 when they should be abstract
* Add load hook for trilogy to match mysql2
Specifying `QueryMethods#and` instead of merely `and` avoids ambiguity
with Ruby's `and` operator, and the `QueryMethods#and` documentation
provides a usage example.
I don't know how prevalent this really is, but I heard several time
about users having memory exhaustion issues caused by the query cache
when dealing with long running jobs.
Overall it seems sensible for this cache not to be entirely unbounded.
`check_pending!` takes a connection that defaults to `Base.connection`
(or migration_connection but right now that's always Base.connection).
This means that we aren't able to loop through all the configs for an
environment because this is a public API that accepts a single
connection. To fix this I've deprecated `check_pending!` in favor of
`check_all_pending!` which will loop through the configs and check for
pending migrations on all the connections.
Example results:
```
Migrations are pending. To resolve this issue, run:
bin/rails db:migrate
You have 3 pending migrations:
db/migrate/20221213152217_create_posts.rb
db/migrate/20230503150812_add_active_column_to_posts.rb
db/secondary_migrate/20230503173111_create_dogs.rb
```
Before this change, only migrations in `db/migrate` or
`db/secondary_migrate` would be output by `ActiveRecord::Migration.check_pending!`.
I chose not to accept a connection or db_config argument for this new
method because it's not super useful. It's more useful to know all
pending migrations. If it becomes problematic, we can reimplement the
connection option on this method (or reintroduce `check_pending!`.