Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider removing enum types as part of db:drop / db:reset #11

Open
michaelherold opened this issue Jun 25, 2020 · 6 comments
Open

Consider removing enum types as part of db:drop / db:reset #11

michaelherold opened this issue Jun 25, 2020 · 6 comments
Assignees
Labels
bug Something isn't working

Comments

@michaelherold
Copy link

Since Postgres defines types in the postgres tables, running db:reset can get you into a situation where you cannot re-run your migrations that define your Postgres enums. As a simple reproduction:

  1. Create a migration where you use create_enum
  2. Run the migration with db:migrate
  3. Reset your database with db:reset

The migration will fail because the type already exists.

This all makes sense, but I wonder if there's a way we could make it so db:drop also drops any enums defined by this gem?

@alassek
Copy link
Owner

alassek commented Jun 25, 2020

What if I changed create_enum to do IF NOT EXISTS? Would that be sufficient?

@michaelherold
Copy link
Author

Yeah, I think that would work. I doubt you'd ever have colliding names in a single app.

Once I finish up what I'm currently working on at work, I'll have an environment for you to play with.

@alassek alassek self-assigned this Jun 26, 2020
@alassek alassek added the bug Something isn't working label Jun 26, 2020
@alassek
Copy link
Owner

alassek commented Dec 8, 2020

It turns out that CREATE TYPE doesn't support IF NOT EXISTS so this is a bit more complicated. Probably going to have to use a DO block.

@stratigos
Copy link

@alassek thanks for this really handy gem! Im really enjoying using it in production.

I frequently reset my localdev databases, and run into this issue as well. In the meantime, I just wrote my own .sql file to destroy my custom enum types when I db:reset or db:setup.

As for IF NOT EXISTS :

It turns out that CREATE TYPE doesn't support IF NOT EXISTS so this is a bit more complicated. Probably going to have to use a DO block.

Im not sure if you meant a Ruby block or a SQL DO, but there are a few solutions for wrapping the CREATE TYPE in some other statement that first performs a check for the custom type. This answer from stackoverflow looks like a good candidate:

DO $$
BEGIN
    IF NOT EXISTS (SELECT 1 FROM pg_type WHERE typname = 'my_type') THEN
        CREATE TYPE my_type AS
        (
            -- add fields...
        );
    END IF;
END$$;

If I had more time Id contribute towards a PR! Perhaps in a few weekends from now.

@alassek
Copy link
Owner

alassek commented Jan 3, 2021

@stratigos yes, that is basically what I had in mind... but I think there's another wrinkle to this. I don't want to blithely wipe out preexisting enums in a production environment, so I think this also needs to tap into the functionality added by rails/rails#22967

So in development, create_enum will automatically drop an existing enum and redefine it. But in production, you will still get the error. I think that's how I want this to work.

@jasonfb

This comment has been minimized.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants