drop_constraint is generated without a constraint name

Issue #221 resolved
Iuri de Silvio
created an issue

I created a column with unique=True:

slug = Column(String(255), nullable=False, unique=True)

It generated a script with

def upgrade():
    op.alter_column('mytable', sa.Column('slug', sa.String(length=255), nullable=False))
    op.create_unique_constraint(None, 'mytable', ['slug'])

def downgrade():
    op.drop_constraint(None, 'mytable')
    op.drop_column('mytable', 'slug')

The upgrade works fine, I suppose the unique constraint name is autogenerated as mytable_slug_key, but the downgrade drop_constraint does not work.

It is obvious to me something is wrong with the script, drop_constraint doesn't have column information to autogenerate the constraint name.

I fixed it defining the constraint name, but it looks like an unexpected behaviour.

Traceback (most recent call last):
  File "manage.py", line 116, in <module>
    manager.run()
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/flask_script/__init__.py", line 423, in run
    result = self.handle(sys.argv[0], sys.argv[1:])
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/flask_script/__init__.py", line 402, in handle
    return handle(app, *positional_args, **kwargs)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/flask_script/commands.py", line 145, in handle
    return self.run(*args, **kwargs)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/flask_migrate/__init__.py", line 107, in downgrade
    command.downgrade(config, revision, sql = sql, tag = tag)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/command.py", line 151, in downgrade
    script.run_env()
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/script.py", line 203, in run_env
    util.load_python_file(self.dir, 'env.py')
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/util.py", line 212, in load_python_file
    module = load_module_py(module_id, path)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/compat.py", line 58, in load_module_py
    mod = imp.load_source(module_id, path, fp)
  File "migrations/env.py", line 71, in <module>
    run_migrations_online()
  File "migrations/env.py", line 64, in run_migrations_online
    context.run_migrations()
  File "<string>", line 7, in run_migrations
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/environment.py", line 688, in run_migrations
    self.get_context().run_migrations(**kw)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/migration.py", line 258, in run_migrations
    change(**kw)
  File "migrations/versions/258d103c6224_mytable_slug.py", line 40, in downgrade
    op.drop_constraint(None, 'mytable')
  File "<string>", line 7, in drop_constraint
  File "<string>", line 1, in <lambda>
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/util.py", line 329, in go
    return fn(*arg, **kw)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/operations.py", line 841, in drop_constraint
    self.impl.drop_constraint(const)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/ddl/impl.py", line 138, in drop_constraint
    self._exec(schema.DropConstraint(const))
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/alembic/ddl/impl.py", line 76, in _exec
    conn.execute(construct, *multiparams, **params)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 729, in execute
    return meth(self, multiparams, params)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 69, in _execute_on_connection
    return connection._execute_ddl(self, multiparams, params)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/engine/base.py", line 777, in _execute_ddl
    compiled = ddl.compile(dialect=dialect)
  File "<string>", line 1, in <lambda>
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/elements.py", line 492, in compile
    return self._compiler(dialect, bind=bind, **kw)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/ddl.py", line 27, in _compiler
    return dialect.ddl_compiler(dialect, self, **kw)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 199, in __init__
    self.string = self.process(self.statement, **compile_kwargs)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 222, in process
    return obj._compiler_dispatch(self, **kwargs)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/ext/compiler.py", line 413, in <lambda>
    lambda *arg, **kw: existing(*arg, **kw))
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/ext/compiler.py", line 451, in __call__
    return fn(element, compiler, **kw)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/visitors.py", line 80, in _compiler_dispatch
    return meth(self, **kw)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 2518, in visit_drop_constraint
    self.preparer.format_constraint(drop.element),
  File "<string>", line 1, in <lambda>
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 2928, in format_constraint
    return self.quote(constraint.name)
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 2893, in quote
    if self._requires_quotes(ident):
  File "/home/iurisilvio/.virtualenvs/fastshop/local/lib/python2.7/site-packages/sqlalchemy/sql/compiler.py", line 2864, in _requires_quotes
    lc_value = value.lower()
AttributeError: 'NoneType' object has no attribute 'lower'

Comments (7)

  1. Iuri de Silvio reporter

    Thanks, the tutorial is enough to understand my problem. Postgres autogenerate this name and alembic does not handle it. I have to fix it in SQLAlchemy level. Makes sense.

  2. P

    alembic generates index name automatically, if i add index=True in a column. Doesn't it makes sense to do the same for unique constraint ? It would be much better if alembic does this:

    op.create_unique_constraint(op.f('email'), 'feedbacks', ['email'])
    

    instead of

    op.create_unique_constraint("None", 'feedbacks', ['email'])
    

    What do you think ?

  3. Log in to comment