Return 400 not 500 for wrong-arity composite-PK row URLs (#2815)

Fixes #2811

Co-authored-by: Zain Dana Harper <zain@aurora-framework.dev>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Zain Dana Harper 2026-07-07 14:19:08 -07:00 committed by GitHub
commit 211e70d4e1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 39 additions and 0 deletions

View file

@ -369,6 +369,40 @@ async def test_row(ds_client):
assert response.json()["rows"] == [{"id": 1, "content": "hello"}]
@pytest.mark.asyncio
@pytest.mark.parametrize("suffix", ("", ".json"))
@pytest.mark.parametrize(
"row_path",
(
"a", # too few components for a two-column primary key
"a,b,c", # too many components for a two-column primary key
),
)
async def test_row_pk_arity_mismatch_returns_400(ds_client, row_path, suffix):
# A row URL with the wrong number of comma-separated primary key
# components used to raise an uncaught sqlite3.ProgrammingError (HTTP 500)
# because the SQL had one bind placeholder per PK column but params were
# only bound for the supplied components. It should be a 400 instead,
# mirroring the existing guard in datasette/views/table.py.
response = await ds_client.get(
"/fixtures/compound_primary_key/{}{}".format(row_path, suffix)
)
assert response.status_code == 400
if suffix == ".json":
assert response.json()["ok"] is False
assert response.json()["status"] == 400
@pytest.mark.asyncio
async def test_row_compound_pk_correct_arity(ds_client):
# The valid two-component URL still resolves the row.
response = await ds_client.get(
"/fixtures/compound_primary_key/a,b.json?_shape=objects"
)
assert response.status_code == 200
assert response.json()["rows"] == [{"pk1": "a", "pk2": "b", "content": "c"}]
@pytest.mark.asyncio
async def test_row_strange_table_name(ds_client):
response = await ds_client.get(