Skip to content

Commit

Permalink
- Fixed bug in batch where if the target table contained multiple
Browse files Browse the repository at this point in the history
foreign keys to the same target table, the batch mechanics would
fail with a "table already exists" error.  Thanks for the help
on this from Lucas Kahlert. fixes #254
  • Loading branch information
zzzeek committed Dec 13, 2014
1 parent 206143c commit b20ad56
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 6 deletions.
23 changes: 17 additions & 6 deletions alembic/batch.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from sqlalchemy import Table, MetaData, Index, select, Column, \
ForeignKeyConstraint, cast
from sqlalchemy import types as sqltypes
from sqlalchemy import schema as sql_schema
from sqlalchemy.util import OrderedDict
from . import util
from .ddl.base import _columns_for_constraint, _is_type_bound
Expand Down Expand Up @@ -174,12 +175,22 @@ def _setup_referent(self, metadata, constraint):
else:
referent_schema = None
if tname != '_alembic_batch_temp':
Table(
tname, metadata,
*[Column(n, sqltypes.NULLTYPE) for n in
[elem._get_colspec().split(".")[-1]
for elem in constraint.elements]],
schema=referent_schema)
key = sql_schema._get_table_key(tname, referent_schema)
if key in metadata.tables:
t = metadata.tables[key]
for elem in constraint.elements:
colname = elem._get_colspec().split(".")[-1]
if not t.c.contains_column(colname):
t.append_column(
Column(colname, sqltypes.NULLTYPE)
)
else:
Table(
tname, metadata,
*[Column(n, sqltypes.NULLTYPE) for n in
[elem._get_colspec().split(".")[-1]
for elem in constraint.elements]],
schema=referent_schema)

def _create(self, op_impl):
self._transfer_elements_to_new_table()
Expand Down
9 changes: 9 additions & 0 deletions docs/build/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@ Changelog
.. changelog::
:version: 0.7.2

.. change::
:tags: bug, batch
:tickets: 254

Fixed bug in batch where if the target table contained multiple
foreign keys to the same target table, the batch mechanics would
fail with a "table already exists" error. Thanks for the help
on this from Lucas Kahlert.

.. change::
:tags: bug, mysql
:tickets: 251
Expand Down
25 changes: 25 additions & 0 deletions tests/test_batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,22 @@ def _fk_fixture(self, table_args=(), table_kwargs={}):
)
return ApplyBatchImpl(t, table_args, table_kwargs)

def _multi_fk_fixture(self, table_args=(), table_kwargs={}):
m = MetaData()
t = Table(
'tname', m,
Column('id', Integer, primary_key=True),
Column('email', String()),
Column('user_id_1', Integer, ForeignKey('user.id')),
Column('user_id_2', Integer, ForeignKey('user.id')),
Column('user_id_3', Integer),
Column('user_id_version', Integer),
ForeignKeyConstraint(
['user_id_3', 'user_id_version'],
['user.id', 'user.id_version'])
)
return ApplyBatchImpl(t, table_args, table_kwargs)

def _named_fk_fixture(self, table_args=(), table_kwargs={}):
m = MetaData()
t = Table(
Expand Down Expand Up @@ -321,6 +337,15 @@ def test_rename_col_fk(self):
"user.id"
)

def test_regen_multi_fk(self):
impl = self._multi_fk_fixture()
self._assert_impl(
impl, colnames=[
'id', 'email', 'user_id_1', 'user_id_2',
'user_id_3', 'user_id_version'],
ddl_contains='FOREIGN KEY(user_id_3, user_id_version) '
'REFERENCES "user" (id, id_version)')

def test_drop_col(self):
impl = self._simple_fixture()
impl.drop_column('tname', column('x'))
Expand Down

0 comments on commit b20ad56

Please sign in to comment.