drop_constraint is generated without a constraint name

Issue #221 resolved
iurisilvio
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. iurisilvio 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