Case insensitive check for foreign key tables

Refs #1515"
This commit is contained in:
Simon Willison 2026-09-24 12:10:42 -07:00
commit 34a7c28ba3
2 changed files with 14 additions and 5 deletions

View file

@ -2317,10 +2317,18 @@ ORDER BY allowed.parent, allowed.child
from datasette.resources import TableResource
other_table = fk["other_table"]
if not await db.table_exists(other_table):
# Foreign key declarations can spell the target with different casing.
target_table = (
await db.execute(
"select name from sqlite_master where type='table' and name=? collate nocase",
[other_table],
)
).first()
if target_table is None:
# SQLite accepts a foreign key to a table that does not exist, and
# linking to it would only lead to a 404
return {}
other_table = target_table[0]
other_column = fk["other_column"]
if other_column is None:
other_pks = await db.primary_keys(other_table)

View file

@ -835,17 +835,18 @@ async def test_table_html_foreign_key_links(ds_client):
@pytest.mark.asyncio
async def test_table_html_foreign_key_to_missing_table_is_not_linked():
@pytest.mark.parametrize("referenced_table", ("authors", "AuThOrS"))
async def test_table_html_foreign_key_to_missing_table_is_not_linked(referenced_table):
# https://github.com/simonw/datasette/issues/1515
ds = Datasette([])
db = ds.add_database(
Database(ds, memory_name="test_foreign_key_to_missing_table"), name="data"
)
await db.execute_write_script("""
await db.execute_write_script(f"""
create table authors (id integer primary key, name text);
create table books (
id integer primary key,
author_id integer references authors(id),
author_id integer references {referenced_table}(id),
missing_id integer references missing_table(id)
);
insert into authors (id, name) values (1, 'Ada');
@ -857,7 +858,7 @@ async def test_table_html_foreign_key_to_missing_table_is_not_linked():
cells = {td["class"][0]: str(td) for td in table.select("tbody tr")[0].select("td")}
assert cells["col-author_id"] == (
'<td class="col-author_id type-int">'
'<a href="/data/authors/1">Ada</a> <em>1</em></td>'
f'<a href="/data/{referenced_table}/1">Ada</a> <em>1</em></td>'
)
assert cells["col-missing_id"] == '<td class="col-missing_id type-int">7</td>'
# The JSON labels are left alone as well