diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-08-18 13:03:49 -0400 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-08-18 16:34:48 -0400 |
| commit | f06c6ba67303e5c75d8ad044494193d8f97b2e2e (patch) | |
| tree | fdbc44d40171a12dc64ae65ad85dab728e900350 /test/dialect/test_sqlite.py | |
| parent | 2051fa2ce9e724e6e77e19067d27d2660e7cd74a (diff) | |
| download | sqlalchemy-f06c6ba67303e5c75d8ad044494193d8f97b2e2e.tar.gz | |
Reflect PK of referred table if referred columns not present
Fixed bug where a FOREIGN KEY that was set up to refer to the parent table
by table name only without the column names would not correctly be
reflected as far as setting up the "referred columns", since SQLite's
PRAGMA does not report on these columns if they weren't given explicitly.
For some reason this was harcoded to assume the name of the local column,
which might work for some cases but is not correct. The new approach
reflects the primary key of the referred table and uses the constraint
columns list as the referred columns list, if the remote column(s) aren't
present in the reflected pragma directly.
Fixes: #4810
Change-Id: I7789f83d68845ae197a782080af8ec64a7bf48cc
Diffstat (limited to 'test/dialect/test_sqlite.py')
| -rw-r--r-- | test/dialect/test_sqlite.py | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/test/dialect/test_sqlite.py b/test/dialect/test_sqlite.py index 1e894da55..b5a162068 100644 --- a/test/dialect/test_sqlite.py +++ b/test/dialect/test_sqlite.py @@ -1770,10 +1770,45 @@ class ConstraintReflectionTest(fixtures.TestBase): ")" ) + conn.execute( + "CREATE TABLE implicit_referred (pk integer primary key)" + ) + # single col foreign key with no referred column given, + # must assume primary key of referred table + conn.execute( + "CREATE TABLE implicit_referrer " + "(id integer REFERENCES implicit_referred)" + ) + + conn.execute( + "CREATE TABLE implicit_referred_comp " + "(pk1 integer, pk2 integer, primary key (pk1, pk2))" + ) + # composite foreign key with no referred columns given, + # must assume primary key of referred table + conn.execute( + "CREATE TABLE implicit_referrer_comp " + "(id1 integer, id2 integer, foreign key(id1, id2) " + "REFERENCES implicit_referred_comp)" + ) + + # worst case - FK that refers to nonexistent table so we cant + # get pks. requires FK pragma is turned off + conn.execute( + "CREATE TABLE implicit_referrer_comp_fake " + "(id1 integer, id2 integer, foreign key(id1, id2) " + "REFERENCES fake_table)" + ) + @classmethod def teardown_class(cls): with testing.db.begin() as conn: for name in [ + "implicit_referrer_comp_fake", + "implicit_referrer", + "implicit_referred", + "implicit_referrer_comp", + "implicit_referred_comp", "m", "main.l", "k", @@ -1892,6 +1927,72 @@ class ConstraintReflectionTest(fixtures.TestBase): ], ) + def test_foreign_key_implicit_parent(self): + inspector = Inspector(testing.db) + fks = inspector.get_foreign_keys("implicit_referrer") + eq_( + fks, + [ + { + "name": None, + "constrained_columns": ["id"], + "referred_schema": None, + "referred_table": "implicit_referred", + "referred_columns": ["pk"], + "options": {}, + } + ], + ) + + def test_foreign_key_composite_implicit_parent(self): + inspector = Inspector(testing.db) + fks = inspector.get_foreign_keys("implicit_referrer_comp") + eq_( + fks, + [ + { + "name": None, + "constrained_columns": ["id1", "id2"], + "referred_schema": None, + "referred_table": "implicit_referred_comp", + "referred_columns": ["pk1", "pk2"], + "options": {}, + } + ], + ) + + def test_foreign_key_implicit_missing_parent(self): + # test when the FK refers to a non-existent table and column names + # aren't given. only sqlite allows this case to exist + inspector = Inspector(testing.db) + fks = inspector.get_foreign_keys("implicit_referrer_comp_fake") + # the referred table doesn't exist but the operation does not fail + eq_( + fks, + [ + { + "name": None, + "constrained_columns": ["id1", "id2"], + "referred_schema": None, + "referred_table": "fake_table", + "referred_columns": [], + "options": {}, + } + ], + ) + + def test_foreign_key_implicit_missing_parent_reflection(self): + # full Table reflection fails however, which is not a new behavior + m = MetaData() + assert_raises_message( + exc.NoSuchTableError, + "fake_table", + Table, + "implicit_referrer_comp_fake", + m, + autoload_with=testing.db, + ) + def test_unnamed_inline_foreign_key(self): inspector = Inspector(testing.db) fks = inspector.get_foreign_keys("e") |
