Skip to content

Generating a migration after setting a schema to a Resource re-creates the Resource's table instead of just setting the schema #731

@gcugnet

Description

@gcugnet

Code of Conduct

  • I agree to follow this project's Code of Conduct

AI Policy

  • I agree to follow this project's AI Policy, or I agree that AI was not used while creating this issue.

Versions

Component Version
Elixir 1.19.2
Erlang/OTP 28
Ash 3.23.1
AshPostgres 2.8.0

Operating system

NixOS 25.11

Current Behavior

In a Ash Resource, when adding the attribute schema in the postgres block, and then running mix ash.codegen, it generates a migration which creates a brand new table rather than just changing the schema in the table definition.

Reproduction

  1. create a new Ash Resource:
    defmodule Prepair.Catalog.NewModel do
      use Ash.Resource,
        domain: Prepair.Catalog,
        data_layer: AshPostgres.DataLayer
    
      postgres do
        repo Prepair.Repo
        table "new_models"
      end
    
      attributes do
        uuid_primary_key :id, public?: true
        attribute :name, :string, public?: true
        create_timestamp :inserted_at, type: :utc_datetime
        update_timestamp :updated_at, type: :utc_datetime
      end
    end
  2. run mix ash.codegen. It generates a file with a migration to create the table. Great!
  3. modify the Ash Resource you previously created, just to add a schema in the postgres definition block:
    [...]
    
      postgres do
        repo Prepair.Repo
        schema "catalog"
        table "new_models"
      end
    
    [...]
  4. run mix ash.codegen again. It generates a new migration file, with an unexpected behaviour: table re-creation instead of modification:
    defmodule Prepair.Repo.Migrations.MoveNewModelsToCatalogSchema do
      @moduledoc """
      Updates resources based on their most recent snapshots.
    
      This file was autogenerated with `mix ash_postgres.generate_migrations`
      """
    
      use Ecto.Migration
    
      def up do
        execute("CREATE SCHEMA IF NOT EXISTS catalog")
      
        create table(:new_models, primary_key: false, prefix: "catalog") do
          add :id, :uuid,
            null: false,
            default: fragment("gen_random_uuid()"),
            primary_key: true
        
          add :name, :text
        
          add :inserted_at, :utc_datetime,
            null: false,
            default: fragment("(now() AT TIME ZONE 'utc')")
        
          add :updated_at, :utc_datetime,
            null: false,
            default: fragment("(now() AT TIME ZONE 'utc')")
        end
      end
    
      def down do
        drop table(:new_models, prefix: "catalog")
      end
    end

Expected Behavior

When modifying an existing Ash Resource to add a schema in the postgres definition block, the generated migration should not attempt to re-create the table under a new schema, but rather changing the schema of the existing table:

defmodule Prepair.Repo.Migrations.MoveNewModelsToCatalogSchema do
  use Ecto.Migration

  def up do
    execute("CREATE SCHEMA IF NOT EXISTS catalog")

    execute("""
    ALTER TABLE new_models
    SET SCHEMA catalog
    """)
  end

  def down do
    execute("""
    ALTER TABLE catalog.new_models
    SET SCHEMA public
    """)
  end
end

NOTE: this example is with a very basic Resource for easy reproduction purpose, but if the Resource has relationships, I guess the generated migration would be more complex than in my "expected" example.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions