Add support for configuring migration strategy on a per-adapter basis.
migration_strategycan now be set on individual adapter classes, overriding the global ActiveRecord.migration_strategy. This allows individual databases to customize migration execution logic:class CustomPostgresStrategy < ActiveRecord::Migration::DefaultStrategy def drop_table(*) # Custom logic specific to PostgreSQL end end ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.migration_strategy = CustomPostgresStrategyAdrianna Chang
Allow either explain format syntax for EXPLAIN queries.
MySQL uses FORMAT=JSON whereas Postgres uses FORMAT JSON. We should be able to accept both formats as options.
Gannon McGibbon
On MySQL parallel test database table reset to use
DELETEinstead ofTRUNCATE.Truncating on MySQL is very slow even on empty or nearly empty tables.
As a result of this change auto increment counters are now no longer reset between test runs on MySQL and the
SKIP_TEST_DATABASE_TRUNCATEenvironment variable no longer has any effect.Donal McBreen
Fix inconsistency in PostgreSQL handling of unbounded time range types
Use
-infinityrather thanNULLfor the lower value of PostgreSQL time ranges when saving records with a Ruby range that begins withnil.create_table :products do |t| t.tsrange :period end class Product < ActiveRecord::Base; end t = Time.utc(2000) Product.create(period: t...nil) Product.create(period: nil...t)Previously this would create two records using different values to represent lower-unbounded and upper-unbounded ranges.
["2000-01-01 00:00:00",infinity) (NULL,"2000-01-01 00:00:00")Now both will use
-infinity/infinitywhich are handled differently thanNULLby some PostgreSQL range operators (e.g.,lower_inf) and support both exclusive and inclusive bounds.["2000-01-01 00:00:00",infinity) [-infinity,"2000-01-01 00:00:00")Martin-Alexander
Database-specific shard swap prohibition
In #43485 (v7.0.0), shard swapping prohibition was introduced as a global switch that applied to all databases.
For the use case of a multi-database application, the global prohibition is overly broad, and so with this change the method
prohibit_shard_swappingwill scope the prohibition to the same connection class (i.e.,connection_specification_name). This allows an application to prohibit shard swapping on a specific database while allowing it on all others.Mike Dalessio
Fix upsert_all when using repeated timestamp attributes.
Gannon McGibbon
PostgreSQL enable drop database FORCE option.
One of the benefits of developing with MySQL is that it allows dropping the current database without first disconnecting clients. As a result developers can use
bin/rails db:resetand similar, without first shutting down instances of the app, Rails consoles, background workers, etc. By default PostgreSQL fails to drop a database when clients are connected and displays the following error:PG::ObjectInUse: ERROR: database "xyz" is being accessed by other users (PG::ObjectInUse)
This is frustrating when working in development where the database may be dropped frequently.
PostgreSQL 13 added the
FORCEoption to theDROP DATABASEstatement (PostgreSQL docs) which automatically disconnects clients before dropping the database. This option is automatically enabled for supported PostgreSQL versions.Steven Webb
Raise specific exception when a prohibited shard change is attempted.
The new
ShardSwapProhibitedErrorexception allows applications and connection-related libraries to more easily recover from this specific scenario. Previously anArgumentErrorwas raised, so the new exception subclassesArgumentErrorfor backwards compatibility.Mike Dalessio
Fix SQLite3 data loss during table alterations with CASCADE foreign keys.
When altering a table in SQLite3 that is referenced by child tables with
ON DELETE CASCADEforeign keys, ActiveRecord would silently delete all data from the child tables. This occurred because SQLite requires table recreation for schema changes, and during this process the original table is temporarily dropped, triggering CASCADE deletes on child tables.The root cause was incorrect ordering of operations. The original code wrapped
disable_referential_integrityinside a transaction, butPRAGMA foreign_keyscannot be modified inside a transaction in SQLite - attempting to do so simply has no effect. This meant foreign keys remained enabled during table recreation, causing CASCADE deletes to fire.The fix reverses the order to follow the official SQLite 12-step ALTER TABLE procedure:
disable_referential_integritynow wraps the transaction instead of being wrapped by it. This ensures foreign keys are properly disabled before the transaction starts and re-enabled after it commits, preventing CASCADE deletes while maintaining data integrity through atomic transactions.Ruy Rocha
Fix negative scopes for enums to include records with
nilvalues.fatkodima
Improve support for SQLite database URIs.
The
db:createanddb:droptasks now correctly handle SQLite database URIs, and the SQLite3Adapter will create the parent directory if it does not exist.Mike Dalessio
Please check [8-1-stable]) for previous changes.