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

Migration downgrade doesn't drop type created by Enum #886

Open
ale7canna opened this issue Aug 19, 2021 · 10 comments
Open

Migration downgrade doesn't drop type created by Enum #886

ale7canna opened this issue Aug 19, 2021 · 10 comments
Labels
autogenerate for enums a long term subject, tagging issues related to this bug Something isn't working

Comments

@ale7canna
Copy link

Given a model definition with an Enum, the resulting autogenerated migration creates a type in the database (Postgresql).
The relative downgrade migration doesn't drop it from the database, making it impossible to perform an upgrade (since this type is already existing).

@zzzeek zzzeek added autogenerate for enums a long term subject, tagging issues related to this awaiting info waiting for the submitter to give more information labels Aug 19, 2021
@zzzeek
Copy link
Member

zzzeek commented Aug 19, 2021

hi -

we are not fixing any autogenrate enum issues in the near future however when you say "downgrade is impossible" I would need to know what migration operation you are referring towards. you can drop enums manually using enum.drop(op.get_bind()).

@ale7canna
Copy link
Author

ale7canna commented Aug 19, 2021

Hi @zzzeek, I'll try to be clearer. Firstly, I want to point out that I'm working on postgres.

The following class definition

class SomeType(enum.Enum):
    foo = 'foo'
    bar = 'bar'


class SomeTestTable(BaseTable):
    __tablename__ = 'some_table'
    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    some_type = Column(Enum(SomeType))

generates the following migration

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('some_table',
    sa.Column('id', postgresql.UUID(as_uuid=True), nullable=False),
    sa.Column('some_type', sa.Enum('foo', 'bar', name='sometype'), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###


def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('some_table')
    # ### end Alembic commands ###

What I see on the database is the creation of a new type sometype performed with this query:

 CREATE TYPE sometype AS ENUM ('foo', 'bar')

If I downgrade this migration, the table is correctly dropped, but not the type. This make impossible to upgrading back to head, since the upgrading operation will try to create again the sometype type.

@CaselIT
Copy link
Member

CaselIT commented Aug 19, 2021

This make impossible to upgrading back to head, since the upgrading operation will try to create again the sometype type.

As mentioned in the downgrade comment, you can adjust the downgrade function.
If you add sa.Enum('foo', 'bar', name='sometype').drop(op.get_bind()) after the drop_table it will work correctly

@CaselIT CaselIT removed the awaiting info waiting for the submitter to give more information label Aug 19, 2021
@ale7canna
Copy link
Author

Thanks guys for your answers. I'll do as you suggest.
Can you confirm this is something you're not going to address in the next releases?

@CaselIT
Copy link
Member

CaselIT commented Aug 20, 2021

Can you confirm this is something you're not going to address in the next releases?

this will not be worked on for the next release.

@CaselIT CaselIT added the bug Something isn't working label Aug 20, 2021
@zzzeek
Copy link
Member

zzzeek commented Aug 20, 2021

enum is a long term issue that requires a full end-to-end approach be devised as there are many complications to the problem, including different database backends, SQLAlchemy's awkward constraints that it generates, and the fact that PostgreSQL wont let you change the elements of an ENUM inside of a transaction. if we make any API decisions or behaviors that conflict with a broader plan to support enum migrations in all forms, it would be much worse. this bug is already an example of early assumptions that don't hold up in practice (SQLAlchemy creates the "enum" for you automatically, but then alembic's "drop table" command doesn't know about the columns). im hoping after SQLAlchemy 2.0 is out and all tools are on python 3 i might have time to start thinking about an all new approach to the whole issue.

@CaselIT
Copy link
Member

CaselIT commented Aug 20, 2021

and the fact that PostgreSQL wont let you change the elements of an ENUM inside of a transaction

Another thing to consider on PostgreSQL is that emun are append only, you cannot remove values from them

@davidjb99
Copy link

I understand this is a difficult problem to solve but it would be a useful feature.

there are many ways to update/drop enums in Postgres outlined here

https://blog.yo1.dog/updating-enum-values-in-postgresql-the-safe-and-easy-way/

frascuchon added a commit to argilla-io/argilla that referenced this issue Jul 21, 2023
<!-- Thanks for your contribution! As part of our Community Growers
initiative 🌱, we're donating Justdiggit bunds in your name to reforest
sub-Saharan Africa. To claim your Community Growers certificate, please
contact David Berenstein in our Slack community or fill in this form
https://tally.so/r/n9XrxK once your PR has been merged. -->

# Description

The last alembic migration definitions fail when using PostgreSQL as the
database. This PR fixes this by allowing upgrade and downgrade properly.
For more info about the problem, see here
sqlalchemy/alembic#886


**Type of change**

(Please delete options that are not relevant. Remember to title the PR
according to the type of change)

- [X] Bug fix (non-breaking change which fixes an issue)

**How Has This Been Tested**

Changes have been tested using a local database to apply migrations
(update and downgrade)

**Checklist**

- [ ] I added relevant documentation
- [ ] follows the style guidelines of this project
- [ ] I did a self-review of my code
- [ ] I made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my
feature works
- [ ] I filled out [the contributor form](https://tally.so/r/n9XrxK)
(see text above)
- [ ] I have added relevant notes to the CHANGELOG.md file (See
https://keepachangelog.com/)

---------

Co-authored-by: Francisco Aranda <[email protected]>
bodik added a commit to bodik/sner4 that referenced this issue Aug 17, 2023
bodik added a commit to bodik/sner4 that referenced this issue Aug 18, 2023
@romanzdk
Copy link

I assume op.execute('DROP TYPE typename;') would also work?

@CaselIT
Copy link
Member

CaselIT commented Sep 25, 2023

sure, you can run any supported sql command by using op.execute

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
autogenerate for enums a long term subject, tagging issues related to this bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants