diff --git a/datasette/stored_queries.py b/datasette/stored_queries.py index a6123daa..d7e1ec99 100644 --- a/datasette/stored_queries.py +++ b/datasette/stored_queries.py @@ -62,7 +62,6 @@ def stored_query_to_dict(query: StoredQuery) -> dict[str, Any]: "description_html": query.description_html, "hide_sql": query.hide_sql, "fragment": query.fragment, - "params": list(query.parameters), "parameters": list(query.parameters), "is_write": query.is_write, "is_private": query.is_private, diff --git a/docs/json_api.rst b/docs/json_api.rst index a561aa9c..54f0b6bd 100644 --- a/docs/json_api.rst +++ b/docs/json_api.rst @@ -1173,7 +1173,6 @@ The following extras are available for arbitrary SQL query responses and stored, "description_html": null, "hide_sql": false, "fragment": null, - "params": [], "parameters": [], "is_write": false, "is_private": false, diff --git a/existing-api.md b/existing-api.md index e11491fe..abb82e2c 100644 --- a/existing-api.md +++ b/existing-api.md @@ -990,7 +990,7 @@ stored_queries.py:55-80): "database": "...", "name": "...", "sql": "...", "title": null, "description": null, "description_html": null, "hide_sql": false, "fragment": null, - "params": ["p"], "parameters": ["p"], + "parameters": ["p"], "is_write": false, "is_private": true, "is_trusted": false, "source": "user", "owner_id": "...", "on_success_message": null, "on_success_message_sql": null, @@ -1000,8 +1000,8 @@ stored_queries.py:55-80): } ``` -`params` and `parameters` are identical lists, both always present. -`private` appears only in list responses. +`private` appears only in list responses. On input (create/update and +`datasette.yaml`), `params` is accepted as an alias for `parameters`. **Default permission rules for queries** (default_permissions/defaults.py): `view-query` is default-allow, but private queries are visible only to their diff --git a/stable-api-recommendations.md b/stable-api-recommendations.md index 8c3131e9..d1388549 100644 --- a/stable-api-recommendations.md +++ b/stable-api-recommendations.md @@ -249,9 +249,12 @@ Concerns: ## 5. Naming and parameter conventions (P2/P3) -- **`params` and `parameters` are duplicate keys** in every stored-query +- ~~**`params` and `parameters` are duplicate keys** in every stored-query object (stored_queries.py:55-80). Delete one before 1.0 (suggest keeping - `parameters`; the write side already accepts both on input). + `parameters`; the write side already accepts both on input).~~ + ✅ **Done** — output objects carry only `parameters` (matching + `/-/query/parameters` and the analyze endpoints); `params` remains an + accepted input alias for API creation and `datasette.yaml` config. - **Three names for the same concept across error/message payloads:** `error`, `errors`, `message`. See §1. - **Boolean query parameters have at least three grammars:** `_nl=on`, diff --git a/tests/test_queries.py b/tests/test_queries.py index c5c1c3cd..11828c4e 100644 --- a/tests/test_queries.py +++ b/tests/test_queries.py @@ -3702,3 +3702,33 @@ async def test_query_delete_api_rejects_trusted_queries(): # datasette.remove_query() remains available for internal use await ds.remove_query("data", "trusted_report") assert await ds.get_query("data", "trusted_report") is None + + +@pytest.mark.asyncio +async def test_stored_query_json_uses_parameters_not_params(): + ds = Datasette( + memory=True, + config={ + "databases": { + "data": { + "queries": { + "with_params": { + "sql": "select :name as name, :age as age", + "params": ["name", "age"], + }, + }, + } + } + }, + ) + ds.add_memory_database("query_parameters_key", name="data") + await ds.invoke_startup() + + definition = (await ds.client.get("/data/with_params/-/definition")).json() + assert definition["query"]["parameters"] == ["name", "age"] + assert "params" not in definition["query"] + + listing = (await ds.client.get("/data/-/queries.json")).json() + query = [q for q in listing["queries"] if q["name"] == "with_params"][0] + assert query["parameters"] == ["name", "age"] + assert "params" not in query