From 39ef137e6760d385dc48d03eccf9b89943636fc7 Mon Sep 17 00:00:00 2001 From: Scott Perry Date: Mon, 8 May 2023 14:10:00 -0700 Subject: [PATCH] Support self-referencing FKs in `create` (#537) --- sqlite_utils/db.py | 2 ++ tests/test_create.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 3c5d91a..19896f8 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -813,6 +813,8 @@ class Database: pk = hash_id # Soundness check foreign_keys point to existing tables for fk in foreign_keys: + if fk.other_table == name and columns.get(fk.other_column): + continue if not any( c for c in self[fk.other_table].columns if c.name == fk.other_column ): diff --git a/tests/test_create.py b/tests/test_create.py index 7252e48..54d125c 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -288,6 +288,25 @@ def test_create_table_works_for_m2m_with_only_foreign_keys( ) +def test_self_referential_foreign_key(fresh_db): + assert [] == fresh_db.table_names() + table = fresh_db.create_table( + "test_table", + columns={ + "id": int, + "ref": int, + }, + pk="id", + foreign_keys=(("ref", "test_table", "id"),), + ) + assert ( + "CREATE TABLE [test_table] (\n" + " [id] INTEGER PRIMARY KEY,\n" + " [ref] INTEGER REFERENCES [test_table]([id])\n" + ")" + ) == table.schema + + def test_create_error_if_invalid_foreign_keys(fresh_db): with pytest.raises(AlterError): fresh_db["one"].insert( @@ -297,6 +316,15 @@ def test_create_error_if_invalid_foreign_keys(fresh_db): ) +def test_create_error_if_invalid_self_referential_foreign_keys(fresh_db): + with pytest.raises(AlterError): + fresh_db["one"].insert( + {"id": 1, "ref_id": 3}, + pk="id", + foreign_keys=(("ref_id", "one", "bad_column"),), + ) + + @pytest.mark.parametrize( "col_name,col_type,not_null_default,expected_schema", (