Define APIs on the MySQL and PostgreSQL connection adapters for building
ChangeColumnDefaultDefinition objects. These provide information on what a
column default change would look like, when called with the same arguments as
would be passed to #change_column_default.
The `remove_check_constraint` method now accepts an `if_exists` option. If set
to true an error won't be raised if the check constraint doesn't exist.
This commit is a combination of PR #45726 and #45718 with some
additional changes to improve wording, testing, and implementation.
Usage:
```ruby
remove_check_constraint :products, name: "price_check", if_exists: true
```
Fixes#45634
Co-authored-by: Margaret Parsa <mparsa@actbluetech.com>
Co-authored-by: Aditya Bhutani <adi_bhutani16@yahoo.in>
Aligns the SQL produced for changing a column default between MySQL and PostgreSQL.
MySQL is currently producing an <ALTER TABLE x CHANGE COLUMN y> query just to
change the default for a column, which is less efficient than using the SET DEFAULT syntax.
Additionally, extracts ChangeColumnDefaultDefinition and moves the SQL generation to the visitor class.
Using `create_or_find_by` in codepaths where most of the time
the record already exist is wasteful on several accounts.
`create_or_find_by` should be the method to use when most of the
time the record doesn't already exist, not a race condition safe
version of `find_or_create_by`.
To make `find_or_create_by` race-condition free, we can search
the record again if the creation failed because of an unicity
constraint.
Co-Authored-By: Alex Kitchens <alexcameron98@gmail.com>
Ref: https://github.com/rails/rails/pull/41659
Mutating the attributes hash requires to workaround the mutation
in `find_or_create_by` etc.
One extra Hash dup is not big deal.
This previously made no difference, but it now saves us reconnecting to
run a ROLLBACK: because we're still inside a transaction at that moment,
we won't be #restorable?.
There's no point attempting to rollback in this case; we can instead
just invalidate the now-lost transaction.
Similarly, even though we can't immediately reconnect for a connection
failure mid-transaction, we can and should drop and prior verification
of the connection: the next out-of-transaction query attempt needs to
fix it, not assume it's working.
Define APIs on the MySQL and PostgreSQL connection adapters for building
ChangeColumnDefinition objects. These provide information on what a
column change would look like, when called with the same arguments as
would be passed to #change_column.
Exposes AlterTable schema definition for adding new columns through new API,
and stores ddl on the schema definition. Refactors existing #add_column method to use
this as an intermediate method to build the create add_column definition.
Exposes CreateIndex schema definition through new API, and stores ddl
on the schema definition. Refactors existing #add_index methods to use
this as an intermediate method to build the create index definition.
Print default parent class for controller, job, and model generators.
Before:
[--parent=PARENT] # The parent class for the generated job
After:
[--parent=PARENT] # The parent class for the generated job
# Default: ApplicationJob
The block can't affect reconnectability, because we'll be re-running it
anyway.
Also, only #reconnect! once per query, to avoid squaring the total
number of permitted retries while attempting to query a pathologically
flakey server.
Connectivity issues need a reconnect to be retried, but there are also
in-server errors that can also be retried (lock timeouts and deadlocks).
To handle this better, we move translation into #with_raw_connection:
it's a much better representation of the boundary between the underlying
adapter library and Active Record's abstractions anyway. (It doesn't
know about the query being run, though, so we let #log enrich that into
the exception later.)
We may be restoring a connection after #with_raw_connection has already
passed #materialize_transactions, so it's important we eagerly return
things to exactly the state they had before.
So far this is just infrastructure: no errors are considered retryable,
and no real queries are marked retryable.
Even in this state, we can drop connection verification from checkout,
and defer it until the first query is ready. But the more interesting
within-reach win will be when 'BEGIN' is retryable, and we can recognise
connectivity-related exceptions.