activerecord-cockroachdb-adapter icon indicating copy to clipboard operation
activerecord-cockroachdb-adapter copied to clipboard

Incorrect db/schema.rb file for Postgres when using Cockroach and Postgres together.

Open jviney opened this issue 2 years ago • 0 comments

In our Rails app we use both Postgres and Cockroach at the same time with Rails 6 multi-database support.

This adapter monkey patches ActiveRecord::ConnectionAdapters::PostgreSQL::Column#serial? in a way that causes the Postgres db/schema.rb file to be incorrectly generated, with primary key values like:

create_table "access_logs", id: :bigint, default: -> { "nextval('admin_access_logs_id_seq'::regclass)" }, force: :cascade do |t|

Instead of:

create_table "access_logs", force: :cascade do |t|

We've applied this patch below to fix the issue so that the @serial value is still respected when it's been supplied for Postgres columns.

module ActiveRecord
  # activerecord-cockroachdb-adapter monkey patches ActiveRecord::ConnectionAdapters::PostgreSQL::Column and
  # overwrites the #serial? method in a way that works for Cockroach, but always returns false for Postgres.
  #
  # This affects the generation of db/schema.rb for Postgres because the primary key column is not identified.
  #
  # Replace the method with one that works for both Postgres and Cockroach.
  #
  # I'm not sure why activerecord-cockroachdb-adapter monkey patches the PostgreSQL::Column class instead of extending
  # it, like it does for other classes.
  module FixDbSchemaDump
    # This combines two methods:
    #  - ActiveRecord::ConnectionAdapters::PostgreSQL::Column#serial?
    #  - ActiveRecord::ConnectionAdapters::CockroachDB::PostgreSQLColumnMonkeyPatch#serial?
    #
    # @serial will always be nil for Cockroach, but may be set for Postgres.
    def serial?
      @serial || default_function == "unique_rowid()"
    end
  end

  ConnectionAdapters::PostgreSQL::Column.class_eval do
    prepend FixDbSchemaDump
  end
end

What's the reason for the CockroachDB adapter monkey patching the PostgresSQL::Column class instead of creating a subclass?

jviney avatar May 05 '22 22:05 jviney