diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2019-10-14 19:26:09 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@bbpush.zzzcomputing.com> | 2019-10-14 19:26:09 +0000 |
commit | 04f50747e66e6b545b7e515d2775298c290a4f58 (patch) | |
tree | 1d57618aa021bdffcad1ac92d1d64eeb9b6295c1 | |
parent | bad52b13b12b52b4eecca43866ab3a55da70a129 (diff) | |
parent | e90002d7fd325218c18f556daab94ab13b46877d (diff) | |
download | alembic-04f50747e66e6b545b7e515d2775298c290a4f58.tar.gz |
Merge "Accommodate for SQLAlchemy 1.4 deferral of index/unique names"
-rw-r--r-- | alembic/autogenerate/compare.py | 13 | ||||
-rw-r--r-- | alembic/util/sqla_compat.py | 43 | ||||
-rw-r--r-- | docs/build/unreleased/sqla14_4911.rst | 7 | ||||
-rw-r--r-- | tests/test_autogen_indexes.py | 42 |
4 files changed, 92 insertions, 13 deletions
diff --git a/alembic/autogenerate/compare.py b/alembic/autogenerate/compare.py index 49ceb21..cacedee 100644 --- a/alembic/autogenerate/compare.py +++ b/alembic/autogenerate/compare.py @@ -338,7 +338,9 @@ def _compare_columns( class _constraint_sig(object): def md_name_to_sql_name(self, context): - return self.name + return sqla_compat._get_constraint_final_name( + self.const, context.dialect + ) def __eq__(self, other): return self.const == other.const @@ -529,7 +531,8 @@ def _compare_indexes_and_uniques( metadata_names = dict( (c.md_name_to_sql_name(autogen_context), c) for c in metadata_unique_constraints.union(metadata_indexes) - if c.name is not None + if isinstance(c, _ix_constraint_sig) + or sqla_compat._constraint_is_named(c.const, autogen_context.dialect) ) conn_uniques_by_name = dict((c.name, c) for c in conn_unique_constraints) @@ -556,7 +559,11 @@ def _compare_indexes_and_uniques( ) metadata_indexes_by_sig = dict((ix.sig, ix) for ix in metadata_indexes) unnamed_metadata_uniques = dict( - (uq.sig, uq) for uq in metadata_unique_constraints if uq.name is None + (uq.sig, uq) + for uq in metadata_unique_constraints + if not sqla_compat._constraint_is_named( + uq.const, autogen_context.dialect + ) ) # assumptions: diff --git a/alembic/util/sqla_compat.py b/alembic/util/sqla_compat.py index 3733142..c3b10dc 100644 --- a/alembic/util/sqla_compat.py +++ b/alembic/util/sqla_compat.py @@ -183,15 +183,11 @@ def _column_kwargs(col): def _get_index_final_name(dialect, idx): - # trying to keep the truncation rules totally localized on the - # SQLA side while also stepping around the quoting issue. Ideally - # the _prepared_index_name() method on the SQLA side would have - # a quoting option or the truncation routine would be broken out. - # - # test for SQLA quoted_name construct, introduced in - # 0.9 or thereabouts. - # this doesn't work in 0.8 and the "quote" option on Index doesn't - # seem to work in 0.8 either. + if sqla_14: + return _get_constraint_final_name(idx, dialect) + + # prior to SQLAlchemy 1.4, work around quoting logic to get at the + # final compiled name without quotes. if hasattr(idx.name, "quote"): # might be quoted_name, might be truncated_name, keep it the # same @@ -201,6 +197,35 @@ def _get_index_final_name(dialect, idx): return dialect.ddl_compiler(dialect, None)._prepared_index_name(idx) +def _get_constraint_final_name(constraint, dialect): + if sqla_14: + if constraint.name is None: + return None + + # for SQLAlchemy 1.4 we would like to have the option to expand + # the use of "deferred" names for constraints as well as to have + # some flexibility with "None" name and similar; make use of new + # SQLAlchemy API to return what would be the final compiled form of + # the name for this dialect. + return dialect.identifier_preparer.format_constraint( + constraint, _alembic_quote=False + ) + else: + return constraint.name + + +def _constraint_is_named(constraint, dialect): + if sqla_14: + if constraint.name is None: + return False + name = dialect.identifier_preparer.format_constraint( + constraint, _alembic_quote=False + ) + return name is not None + else: + return constraint.name is not None + + def _dialect_supports_comments(dialect): if sqla_120: return dialect.supports_comments diff --git a/docs/build/unreleased/sqla14_4911.rst b/docs/build/unreleased/sqla14_4911.rst new file mode 100644 index 0000000..71463cb --- /dev/null +++ b/docs/build/unreleased/sqla14_4911.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: change, compatibility + + Some internal modifications have been made to how the names of indexes and + unique constraints work to make use of new functions added in SQLAlchemy + 1.4, so that SQLAlchemy has more flexibility over how naming conventions + may be applied to these objects. diff --git a/tests/test_autogen_indexes.py b/tests/test_autogen_indexes.py index c8eaffb..416444c 100644 --- a/tests/test_autogen_indexes.py +++ b/tests/test_autogen_indexes.py @@ -18,6 +18,7 @@ from alembic.testing import engines from alembic.testing import eq_ from alembic.testing import TestBase from alembic.testing.env import staging_env +from alembic.util import sqla_compat from ._autogen_fixtures import AutogenFixtureTest py3k = sys.version_info >= (3,) @@ -204,7 +205,12 @@ class AutogenerateUniqueIndexTest(AutogenFixtureTest, TestBase): eq_(diffs[0][0], "add_table") eq_(diffs[1][0], "add_index") - eq_(diffs[1][1].name, "ix_extra_foo") + eq_( + sqla_compat._get_constraint_final_name( + diffs[1][1], config.db.dialect + ), + "ix_extra_foo", + ) eq_(diffs[2][0], "add_index") eq_(diffs[2][1].name, "newtable_idx") @@ -257,6 +263,40 @@ class AutogenerateUniqueIndexTest(AutogenFixtureTest, TestBase): diffs = self._fixture(m1, m2) eq_(diffs, []) + def test_nothing_changed_implicit_uq_w_naming_conv(self): + m1 = MetaData( + naming_convention={ + "ix": "ix_%(column_0_label)s", + "uq": "uq_%(column_0_label)s", + } + ) + m2 = MetaData( + naming_convention={ + "ix": "ix_%(column_0_label)s", + "uq": "uq_%(column_0_label)s", + } + ) + + Table( + "nothing_changed", + m1, + Column("id1", Integer, primary_key=True), + Column("id2", Integer, primary_key=True), + Column("x", String(20), unique=True), + mysql_engine="InnoDB", + ) + + Table( + "nothing_changed", + m2, + Column("id1", Integer, primary_key=True), + Column("id2", Integer, primary_key=True), + Column("x", String(20), unique=True), + mysql_engine="InnoDB", + ) + diffs = self._fixture(m1, m2) + eq_(diffs, []) + def test_nothing_changed_two(self): m1 = MetaData() m2 = MetaData() |