Remove duplicate params key from stored query JSON objects

Every stored-query object carried the same list of parameter names
twice, as both "params" and "parameters". Output objects now carry only
"parameters", consistent with /-/query/parameters and the two analyze
endpoints (and distinct from the "params" bound-values dictionary used
by the query extra and /-/execute-write). "params" remains an accepted
input alias for query creation, update and datasette.yaml config.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GrHZSypDfMnym1tM5XJAFZ
This commit is contained in:
Claude 2026-07-04 16:00:25 +00:00
commit 6488b7a30e
No known key found for this signature in database
5 changed files with 38 additions and 7 deletions

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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`,

View file

@ -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