Estou tentando alterar o tipo de uma coluna de ENUM para INTEGER (que também é uma chave estrangeira) no PostgreSQL usando Alembic. No entanto, quando tento atualizar a migração, encontro o seguinte erro:
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.CannotCoerce) não é possível converter o tipo serie_enum para inteiro LINHA 1: ...R COLUNA serie_aluno TIPO INTEIRO USANDO serie_aluno::integer
[SQL: ALTER TABLE aluno ALTER COLUNA serie_aluno TIPO INTEIRO USANDO serie_aluno::integer]
Aqui está o arquivo de migração gerado pelo Alembic:
def upgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('aluno', 'serie_aluno',
existing_type=postgresql.ENUM('6', '7', '8', '9', name='serie_enum'),
type_=sa.Integer(),
existing_nullable=False,
postgresql_using="NULL")
op.create_foreign_key(None, 'aluno', 'serie', ['serie_aluno'], ['id_serie'])
# ### end Alembic commands ###
def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'aluno', type_='foreignkey')
op.alter_column('aluno', 'serie_aluno',
existing_type=sa.Integer(),
type_=postgresql.ENUM('6', '7', '8', '9', name='serie_enum'),
existing_nullable=False)
# ### end Alembic commands ###
Como posso converter com sucesso uma coluna de ENUM para INTEGER e, ao mesmo tempo, garantir que a restrição de chave estrangeira seja criada corretamente?
Para quem estiver interessado, a solução foi bem simples, basicamente adicionei o comando sql como meu amigo Erwin sugeriu.
Não há nenhuma conversão definida do seu tipo de enumeração personalizado
serie_aluno
parainteger
. (A menos que você crie uma conversão explicitamente.)Mas tudo pode ser convertido para
text
. Se todos os valores enum forem representados por literais inteiros válidos, você pode usartext
como trampolim:Para então adicionar uma
FOREIGN KEY
restrição apontando para umainteger
coluna:Ou faça isso em um único comando ALTER TABLE :
violino
Isso é meio bagunçado, mas eu tive que tornar a coluna anulável com uma alteração antes de poder fazer a alteração subsequente para alterar o tipo e definir todos os valores para
NULL
. Você pode realmente migrar o enum para ints codificados se você souber o mapeamento e usar umaCASE
declaração que você disse que não precisava, mas eu achei muito legal.