Resolve implicit primary key references in table.foreign_keys

For foreign keys declared as "REFERENCES other_table" with no explicit
columns, PRAGMA foreign_key_list returns None for the referenced
column. The foreign_keys property now resolves these to the other
table's primary key columns, so other_column=None unambiguously
indicates a compound foreign key.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Simon Willison 2026-07-05 14:42:30 -07:00
commit 8443d7f3ba
2 changed files with 43 additions and 0 deletions

View file

@ -2075,6 +2075,12 @@ class Table(Queryable):
other_table = rows[0][1]
columns = [row[2] for row in rows]
other_columns = [row[3] for row in rows]
if all(c is None for c in other_columns):
# "REFERENCES other_table" with no columns - the pragma
# returns None, meaning the other table's primary key
other_table_pks = self.db.table(other_table).pks
if len(other_table_pks) == len(columns):
other_columns = other_table_pks
is_compound = len(rows) > 1
fks.append(
ForeignKey(

View file

@ -408,3 +408,40 @@ def test_transform_preserves_compound_foreign_key_on_delete():
assert fk.is_compound is True
assert fk.on_delete == "CASCADE"
assert "ON DELETE CASCADE" in db["courses"].schema
def test_implicit_primary_key_reference_is_resolved():
# REFERENCES authors (no column) has "to" of None in the pragma -
# it should be resolved to the primary key of the other table
db = Database(memory=True)
db.executescript("""
CREATE TABLE authors (author_id INTEGER PRIMARY KEY);
CREATE TABLE books (
id INTEGER PRIMARY KEY,
author_id INTEGER REFERENCES authors
);
""")
fk = db["books"].foreign_keys[0]
assert fk.is_compound is False
assert fk.other_column == "author_id"
assert fk.other_columns == ["author_id"]
def test_implicit_compound_primary_key_reference_is_resolved():
db = Database(memory=True)
db.executescript("""
CREATE TABLE departments (
campus_name TEXT NOT NULL,
dept_code TEXT NOT NULL,
PRIMARY KEY (campus_name, dept_code)
);
CREATE TABLE courses (
course_code TEXT PRIMARY KEY,
campus_name TEXT NOT NULL,
dept_code TEXT NOT NULL,
FOREIGN KEY (campus_name, dept_code) REFERENCES departments
);
""")
fk = db["courses"].foreign_keys[0]
assert fk.is_compound is True
assert fk.other_columns == ["campus_name", "dept_code"]