From: Sean Dunn Date: Fri, 29 Jun 2018 14:26:57 +0000 (-0400) Subject: Add unique_constraint_name to MSSQL FK reflection X-Git-Tag: rel_1_3_0b1~149^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca94ea8ab583f8ab366ee5971bfc1bdd96e54cc9;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git Add unique_constraint_name to MSSQL FK reflection Fixed bug in MSSQL reflection where when two same-named tables in different schemas had same-named primary key constraints, foreign key constraints referring to one of the tables would have their columns doubled, causing errors. Pull request courtesy Sean Dunn. Fixes: #4228 Change-Id: I7dabaaee0944e1030048826ba39fc574b0d63031 Pull-request: https://github.com/zzzeek/sqlalchemy/pull/457 --- diff --git a/doc/build/changelog/unreleased_12/4228.rst b/doc/build/changelog/unreleased_12/4228.rst new file mode 100644 index 0000000000..c3a436da33 --- /dev/null +++ b/doc/build/changelog/unreleased_12/4228.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, mssql + :tickets: 4228 + + Fixed bug in MSSQL reflection where when two same-named tables in different + schemas had same-named primary key constraints, foreign key constraints + referring to one of the tables would have their columns doubled, causing + errors. Pull request courtesy Sean Dunn. diff --git a/lib/sqlalchemy/dialects/mssql/base.py b/lib/sqlalchemy/dialects/mssql/base.py index bc3905535e..c10b75c02c 100644 --- a/lib/sqlalchemy/dialects/mssql/base.py +++ b/lib/sqlalchemy/dialects/mssql/base.py @@ -2251,6 +2251,8 @@ class MSDialect(default.DefaultDialect): C.c.constraint_name == RR.c.constraint_name, R.c.constraint_name == RR.c.unique_constraint_name, + R.c.constraint_schema == + RR.c.unique_constraint_schema, C.c.ordinal_position == R.c.ordinal_position ), order_by=[RR.c.constraint_name, R.c.ordinal_position] diff --git a/lib/sqlalchemy/dialects/mssql/information_schema.py b/lib/sqlalchemy/dialects/mssql/information_schema.py index 1034587057..3682fae481 100644 --- a/lib/sqlalchemy/dialects/mssql/information_schema.py +++ b/lib/sqlalchemy/dialects/mssql/information_schema.py @@ -103,6 +103,8 @@ key_constraints = Table("KEY_COLUMN_USAGE", ischema, key="column_name"), Column("CONSTRAINT_NAME", CoerceUnicode, key="constraint_name"), + Column("CONSTRAINT_SCHEMA", CoerceUnicode, + key="constraint_schema"), Column("ORDINAL_POSITION", Integer, key="ordinal_position"), schema="INFORMATION_SCHEMA") diff --git a/lib/sqlalchemy/testing/provision.py b/lib/sqlalchemy/testing/provision.py index 8abfa3301c..4c749d382d 100644 --- a/lib/sqlalchemy/testing/provision.py +++ b/lib/sqlalchemy/testing/provision.py @@ -369,6 +369,7 @@ def _mssql_create_db(cfg, eng, ident): "ALTER DATABASE %s SET READ_COMMITTED_SNAPSHOT ON" % ident) conn.execute("use %s" % ident) conn.execute("create schema test_schema") + conn.execute("create schema test_schema_2") @_drop_db.for_db("mssql") diff --git a/test/dialect/mssql/test_reflection.py b/test/dialect/mssql/test_reflection.py index d3b270d2f5..720d6ec18f 100644 --- a/test/dialect/mssql/test_reflection.py +++ b/test/dialect/mssql/test_reflection.py @@ -118,6 +118,50 @@ class ReflectionTest(fixtures.TestBase, ComparesTables, AssertsCompiledSQL): assert isinstance(t1.c.id.type, Integer) assert isinstance(t1.c.data.type, types.NullType) + @testing.provide_metadata + def test_cross_schema_fk_pk_name_overlaps(self): + # test for issue #4228 + metadata = self.metadata + + Table( + "subject", metadata, + Column("id", Integer), + PrimaryKeyConstraint("id", name="subj_pk"), + schema=testing.config.test_schema, + ) + + Table( + "referrer", metadata, + Column("id", Integer, primary_key=True), + Column( + 'sid', + ForeignKey( + "%s.subject.id" % testing.config.test_schema, + name='fk_subject') + ), + schema=testing.config.test_schema + ) + + Table( + "subject", metadata, + Column("id", Integer), + PrimaryKeyConstraint("id", name="subj_pk"), + schema=testing.config.test_schema_2 + ) + + metadata.create_all() + + insp = inspect(testing.db) + eq_( + insp.get_foreign_keys("referrer", testing.config.test_schema), + [{ + 'name': 'fk_subject', + 'constrained_columns': ['sid'], + 'referred_schema': 'test_schema', + 'referred_table': 'subject', + 'referred_columns': ['id']}] + ) + @testing.provide_metadata def test_db_qualified_items(self): metadata = self.metadata