Skip to content

A (mostly) minimal reproduction of Rails 8 `db/structure.sql` breaking changes for Postgres.

Notifications You must be signed in to change notification settings

ggambetti/rails-8-postgres-broken-sql-dump

Repository files navigation

This repository documents a breaking change with Rails 8, when running Postgresql databases.

The Change

Running db:migrate on a fresh database now loads the schema before running migrations. Subsequent calls will run pending migrations. (If you need the previous behavior of running migrations from scratch instead of loading the schema file, this can be done by running db:migrate:reset which will drop and recreate the database before running migrations) -- Notable Changes (Ruby on Rails 8.0 Release Notes)

Changed in #52820.

ActiveRecord schema format :sql

In 7.2 ActiveRecord delegates Postgresql tooling (pg_dump) when the schema format is set to :sql (docs).

This is still true in 8.0.

The incompatibility

When multiple schema_search_paths are used across different environments (eg: develpment and production) or across different installations (eg: SaaS and on-prem), ActiveRecord doesn't notice the incompatibility and continues to attempt to load the incompatible db/structure.sql file. This usually fails, but in the situation that customers are running an on-prem instance and it succeeds, this behaviour can pollute schemas in use by other applications that are outside of the control of the Rails application.

eg: in this repository, loading the production schema into development when running bash repro.sh.

The issue with pg_dump

Rails has previously run into issues with pg_dump and Postgres schemas: (#22345). The issue being that using multiple schemas required filtering the pg_dump command to only export schemas that are in use by the Rails application.

Unfortunately, from the pg_dump documentation, there's no mechanism to omit the schema names and create the export in a way that makes it schema agnostic.

What Rails can do about it

Rails is already processing the output from pg_dump:

  • to remove \restrict and \unrestrict lines (#55510)
  • to remove SQL comments (#28154)

It should be possible for Rails to detect schema incompatibility, and not load db/structure.sql when the schema(s) it was generated with do not match the schema(s) it would be loaded into.

To accomplish this, Rails could write a header to the file containing schema data, and then read it out before loading the file into Posgresql.

About

A (mostly) minimal reproduction of Rails 8 `db/structure.sql` breaking changes for Postgres.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published