{"id": 1059555791, "node_id": "I_kwDOBm6k_c4_J4nP", "number": 1527, "title": "Columns starting with an underscore behave poorly in filters", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 7, "created_at": "2021-11-22T01:01:36Z", "updated_at": "2022-01-14T00:57:08Z", "closed_at": "2022-01-14T00:57:08Z", "author_association": "OWNER", "pull_request": null, "body": "Similar bug to #1525 (and #1506 before it). Start on https://latest.datasette.io/fixtures/facetable?_facet=_neighborhood - then select a neighborhood - then try to remove that filter using the little \"x\" and submitting the form again.\r\n\r\n![filter-bug](https://user-images.githubusercontent.com/9599/142786754-31d265a2-944d-4ea2-af6f-305d445a2ccb.gif)\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1527/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1087931918, "node_id": "I_kwDOBm6k_c5A2IYO", "number": 1579, "title": "`.execute_write(... block=True)` should be the default behaviour", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 7, "created_at": "2021-12-23T18:54:28Z", "updated_at": "2022-01-13T22:28:08Z", "closed_at": "2021-12-23T19:18:26Z", "author_association": "OWNER", "pull_request": null, "body": "Every single piece of code I've written against the write APIs has used the `block=True` option to wait for the result.\r\n\r\nWithout that, it instead fires the write into the queue but then continues even before it has finished executing.\r\n\r\n`block=True` should clearly be the default behaviour here!", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1579/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1076388044, "node_id": "I_kwDOBm6k_c5AKGDM", "number": 1547, "title": "Writable canned queries fail to load custom templates", "user": {"value": 127565, "label": "wragge"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 6, "created_at": "2021-12-10T03:31:48Z", "updated_at": "2022-01-13T22:27:59Z", "closed_at": "2021-12-19T21:12:00Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "I've created a canned query with `\"write\": true` set. I've also created a custom template for it, but the template doesn't seem to be found. If I look in the HTML I see (`stock_exchange` is the db name):\r\n\r\n``\r\n\r\nMy non-writeable canned queries pick up custom templates as expected, and if I look at their HTML I see the canned query name added to the templates considered (the canned query here is `date_search`):\r\n\r\n``\r\n\r\nSo it seems like the writeable canned query is behaving differently for some reason. Is it an authentication thing? I'm using the built in `--root` authentication.\r\n\r\nThanks!\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1547/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1077893013, "node_id": "I_kwDOBm6k_c5AP1eV", "number": 1551, "title": "`keep_blank_values=True` when parsing `request.args`", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 3, "created_at": "2021-12-12T19:53:07Z", "updated_at": "2022-01-13T22:26:04Z", "closed_at": "2021-12-12T20:02:01Z", "author_association": "OWNER", "pull_request": null, "body": "This code in `TableView` wouldn't be necessary: https://github.com/simonw/datasette/blob/492f9835aa7e90540dd0c6324282b109f73df71b/datasette/views/table.py#L396-L399\r\n\r\nIf that happened here instead: https://github.com/simonw/datasette/blob/492f9835aa7e90540dd0c6324282b109f73df71b/datasette/utils/asgi.py#L98-L100\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1518#issuecomment-991827468_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1551/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1078702875, "node_id": "I_kwDOBm6k_c5AS7Mb", "number": 1552, "title": "Allow to set `facets_array` in metadata (like current `facets`)", "user": {"value": 3556, "label": "davidbgk"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 9, "created_at": "2021-12-13T16:00:44Z", "updated_at": "2022-01-13T22:26:15Z", "closed_at": "2021-12-16T18:47:48Z", "author_association": "CONTRIBUTOR", "pull_request": null, "body": "For now, you can set a `facets` value (array) in your metadata file but I couldn't find a way to set a `facets_array` in order to provide default facets for arrays (like tags). My use-case is to access to [that kind of view](https://latest.datasette.io/fixtures/facetable?_facet_array=tags) by default without URL's parameters as with other default facets.\r\n\r\n_I'm new to datasette, and I'm willing to help with a PR if that is not already implemented and I missed it!_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1552/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1079149656, "node_id": "I_kwDOBm6k_c5AUoRY", "number": 1555, "title": "Optimize all those calls to index_list and foreign_key_list", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 27, "created_at": "2021-12-13T23:50:56Z", "updated_at": "2022-01-13T22:27:32Z", "closed_at": "2021-12-19T20:55:59Z", "author_association": "OWNER", "pull_request": null, "body": "On the first hit to a restarted index I'm seeing this in the SQL traces: https://latest-with-plugins.datasette.io/github/commits?_trace=1\r\n\r\n\"image\"\r\n\r\nI imagine this could be sped up a lot using tricks like this one from the SQLite documentation: https://sqlite.org/pragma.html#pragfunc\r\n\r\n```sql\r\nSELECT DISTINCT m.name || '.' || ii.name AS 'indexed-columns'\r\n FROM sqlite_schema AS m,\r\n pragma_index_list(m.name) AS il,\r\n pragma_index_info(il.name) AS ii\r\n WHERE m.type='table'\r\n ORDER BY 1;\r\n```\r\nhttps://latest-with-plugins.datasette.io/fixtures?sql=SELECT+DISTINCT+m.name+%7C%7C+%27.%27+%7C%7C+ii.name+AS+%27indexed-columns%27%0D%0A++FROM+sqlite_schema+AS+m%2C%0D%0A+++++++pragma_index_list%28m.name%29+AS+il%2C%0D%0A+++++++pragma_index_info%28il.name%29+AS+ii%0D%0A+WHERE+m.type%3D%27table%27%0D%0A+ORDER+BY+1%3B", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1555/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1081318247, "node_id": "I_kwDOBm6k_c5Ac5tn", "number": 1556, "title": "Show count of facet values always, not just for `?_facet_size=max`", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 1, "created_at": "2021-12-15T17:49:01Z", "updated_at": "2022-01-13T22:26:07Z", "closed_at": "2021-12-15T17:58:06Z", "author_association": "OWNER", "pull_request": null, "body": "> You've caused me to rethink this feature - I no longer think there's value in only showing these numbers if `?_facet_size=max` as opposed to all of the time.\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1423#issuecomment-995023410_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1556/reactions\", \"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 1, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1082564912, "node_id": "I_kwDOBm6k_c5AhqEw", "number": 1557, "title": "`?_nosuggest=1` parameter for disabling facet suggestions on table view", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 1, "created_at": "2021-12-16T19:21:42Z", "updated_at": "2022-01-13T22:26:48Z", "closed_at": "2021-12-16T19:24:59Z", "author_association": "OWNER", "pull_request": null, "body": "Found I wanted this while I was debugging #625 just to clean up the debug traces, but it makes sense as a partner to `?_nofacet=1` and `?_nocount=1` from #1350 and #1353.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1557/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1082746149, "node_id": "I_kwDOBm6k_c5AiWUl", "number": 1560, "title": "Table page title has \"where where\" in it", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 0, "created_at": "2021-12-17T00:05:48Z", "updated_at": "2022-01-13T22:28:35Z", "closed_at": "2022-01-13T22:20:15Z", "author_association": "OWNER", "pull_request": null, "body": "Just noticed this while working on #1518.\r\n\r\n```\r\n% curl -s 'https://latest.datasette.io/fixtures/facetable?_sort=pk&on_earth__exact=1' | grep -C 1 ''\r\n<head>\r\n <title>fixtures: facetable: 14 rows\r\n where where on_earth = 1 sorted by pk\r\n```", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1560/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083669410, "node_id": "I_kwDOBm6k_c5Al3ui", "number": 1566, "title": "Release Datasette 0.60", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 6, "created_at": "2021-12-17T22:58:12Z", "updated_at": "2022-01-14T01:59:55Z", "closed_at": "2022-01-14T01:59:55Z", "author_association": "OWNER", "pull_request": null, "body": "Using this as a tracking issue. I'm hoping to get the bulk of the JSON redesign work from the refactor in #1554 in for this release.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1566/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083573206, "node_id": "I_kwDOBm6k_c5AlgPW", "number": 1563, "title": "Datasette(... files=) should not be a required argument", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 2, "created_at": "2021-12-17T19:54:18Z", "updated_at": "2022-01-13T22:27:18Z", "closed_at": "2021-12-18T02:19:40Z", "author_association": "OWNER", "pull_request": null, "body": "```pycon\r\n>>> ds = Datasette(memory=True)\r\nTraceback (most recent call last):\r\n File \"\", line 1, in \r\nTypeError: __init__() missing 1 required positional argument: 'files'\r\n>>> ds = Datasette(memory=True, files=[])\r\n```\r\nI wanted to create an in-memory Datasette for running some tests, no point in forcing me to pass `files=[]` to do that.", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1563/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083581011, "node_id": "I_kwDOBm6k_c5AliJT", "number": 1564, "title": "_prepare_connection not called on write connections", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 1, "created_at": "2021-12-17T20:06:47Z", "updated_at": "2022-01-20T21:29:43Z", "closed_at": "2021-12-18T01:58:44Z", "author_association": "OWNER", "pull_request": null, "body": "I was trying to initalize SpatiaLite in a write connection:\r\n```pycon\r\n>>> from datasette.app import Datasette\r\n>>> ds = Datasette(memory=True, files=[], sqlite_extensions=[\"spatialite\"])\r\n>>> db = ds.add_memory_database('geo')\r\n>>> await db.execute_write(\"select InitSpatialMetadata(1)\")\r\nUUID('3f143baa-4e3d-5842-a36f-4fa2f683b72f')\r\nno such function: InitSpatialMetadata\r\n```\r\nIt looks like the code that loads additional modules only works on read-only connections, not on write connections:\r\n\r\nhttps://github.com/simonw/datasette/blob/92a5280d2e75c39424a75ad6226fc74400ae984f/datasette/database.py#L146-L153\r\n\r\nCompared to:\r\n\r\nhttps://github.com/simonw/datasette/blob/92a5280d2e75c39424a75ad6226fc74400ae984f/datasette/database.py#L124-L132", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1564/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083921371, "node_id": "I_kwDOBm6k_c5Am1Pb", "number": 1570, "title": "Separate db.execute_write() into three methods", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 2, "created_at": "2021-12-18T18:45:54Z", "updated_at": "2022-01-13T22:27:38Z", "closed_at": "2021-12-18T18:57:25Z", "author_association": "OWNER", "pull_request": null, "body": "> Rather than adding a `executemany=True` parameter, I'm now thinking a better design might be to have three methods:\r\n>\r\n> - `db.execute_write(sql, params=None, block=False)`\r\n> - `db.execute_write_script(sql, block=False)`\r\n> - `db.execute_write_many(sql, params_seq, block=False)`\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1555#issuecomment-997267416_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1570/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083927147, "node_id": "I_kwDOBm6k_c5Am2pr", "number": 1571, "title": "Track number of executions for execute_write_many() in traces", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 0, "created_at": "2021-12-18T19:16:17Z", "updated_at": "2022-01-13T22:27:49Z", "closed_at": "2021-12-19T20:30:40Z", "author_association": "OWNER", "pull_request": null, "body": "Spotted while working on #1555\r\n\r\n\"image\"\r\n\r\nThere's no indication there of how many times `execute_write_many()` executed the SQL.\r\n\r\nSolving this is a tiny bit tricky because `params_seq` is an iterator that we don't want to exhaust before passing it to `conn.executemany()` - so we need to instead wrap it in something that counts how many times it was called.\r\n\r\nBut then we need a way to attach that to the trace here: https://github.com/simonw/datasette/blob/d637ed46762fdbbd8e32b86f258cd9a53c1cfdc7/datasette/database.py#L115-L122\r\n\r\nSo probably need to redesign the `trace()` decorator to allow extra pairs to be attached to it within the `with` statement.\r\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1571/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083718998, "node_id": "I_kwDOBm6k_c5AmD1W", "number": 1567, "title": "Remove undocumented sqlite_functions mechanism", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 0, "created_at": "2021-12-18T01:51:10Z", "updated_at": "2022-01-13T22:27:04Z", "closed_at": "2021-12-18T01:54:46Z", "author_association": "OWNER", "pull_request": null, "body": "I added this in 0b8c1b0a6da9cb8ac0d28cc90dd783de87554036 but it's never been documented and the same thing can now be achieved using the `prepare_connection` plugin hook.\r\n\r\nhttps://github.com/simonw/datasette/blob/0c91e59d2bbfc08884cfcf5d1b902a2f4968b7ff/datasette/app.py#L262\r\n\r\nhttps://github.com/simonw/datasette/blob/0c91e59d2bbfc08884cfcf5d1b902a2f4968b7ff/datasette/app.py#L551-L552\r\n\r\nIt's used here in the tests:\r\n\r\nhttps://github.com/simonw/datasette/blob/69244a617b1118dcbd04a8f102173f04680cf08c/tests/fixtures.py#L156", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1567/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083726550, "node_id": "I_kwDOBm6k_c5AmFrW", "number": 1568, "title": "Trace should show queries on the write connection too", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 2, "created_at": "2021-12-18T02:34:12Z", "updated_at": "2022-01-13T22:27:23Z", "closed_at": "2021-12-18T02:42:34Z", "author_association": "OWNER", "pull_request": null, "body": "> Here's why - `trace` only applies to read, not write SQL operations: https://github.com/simonw/datasette/blob/7c8f8aa209e4ba7bf83976f8495d67c28fbfca24/datasette/database.py#L209-L211\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1555#issuecomment-997128508_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1568/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1083895395, "node_id": "I_kwDOBm6k_c5Amu5j", "number": 1569, "title": "db.execute_write(..., executescript=True) parameter", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 2, "created_at": "2021-12-18T18:20:47Z", "updated_at": "2022-01-13T22:27:27Z", "closed_at": "2021-12-18T18:34:18Z", "author_association": "OWNER", "pull_request": null, "body": "> Idea: teach `execute_write` to accept an optional `executescript=True` parameter, like this:\r\n```diff\r\ndiff --git a/datasette/database.py b/datasette/database.py\r\nindex 468e936..1a424f5 100644\r\n--- a/datasette/database.py\r\n+++ b/datasette/database.py\r\n@@ -94,10 +94,14 @@ class Database:\r\n f\"file:{self.path}{qs}\", uri=True, check_same_thread=False\r\n )\r\n \r\n- async def execute_write(self, sql, params=None, block=False):\r\n+ async def execute_write(self, sql, params=None, executescript=False, block=False):\r\n+ assert not executescript and params, \"Cannot use params with executescript=True\"\r\n def _inner(conn):\r\n with conn:\r\n- return conn.execute(sql, params or [])\r\n+ if executescript:\r\n+ return conn.executescript(sql)\r\n+ else:\r\n+ return conn.execute(sql, params or [])\r\n \r\n with trace(\"sql\", database=self.name, sql=sql.strip(), params=params):\r\n results = await self.execute_write_fn(_inner, block=block)\r\n```\r\n\r\n_Originally posted by @simonw in https://github.com/simonw/datasette/issues/1555#issuecomment-997248364_", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1569/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1084007781, "node_id": "I_kwDOBm6k_c5AnKVl", "number": 1572, "title": "\"Query took\" should be \"Queries took\"", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 0, "created_at": "2021-12-19T04:03:00Z", "updated_at": "2022-01-13T22:27:43Z", "closed_at": "2021-12-19T04:03:24Z", "author_association": "OWNER", "pull_request": null, "body": "This is misleading, since usually there have been more than one query executed:\r\n\r\n![CleanShot 2021-12-18 at 20 02 35@2x](https://user-images.githubusercontent.com/9599/146663457-9c4c2900-5cc0-4650-a565-bb1ff0b8a725.png)\r\n\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1572/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1097101917, "node_id": "I_kwDOBm6k_c5BZHJd", "number": 1588, "title": "`explain query plan select` is too strict about whitespace", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 3, "created_at": "2022-01-09T04:22:42Z", "updated_at": "2022-01-13T22:28:19Z", "closed_at": "2022-01-13T20:35:05Z", "author_association": "OWNER", "pull_request": null, "body": "`explain query plan select * from facetable` is allowed: https://latest.datasette.io/fixtures?sql=explain+query+plan+select+*+from+facetable\r\n\r\nBut... `explain query plan select * from facetable` (with two spaces before the `select`) returns a \"Statement must be a SELECT\" error: https://latest.datasette.io/fixtures?sql=explain+query+plan++select+*+from+facetable", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1588/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1099723916, "node_id": "I_kwDOBm6k_c5BjHSM", "number": 1590, "title": "Table+query JSON and CSV links broken when using `base_url` setting", "user": {"value": 1001306, "label": "eelkevdbos"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 11, "created_at": "2022-01-11T23:46:39Z", "updated_at": "2022-01-14T01:16:34Z", "closed_at": "2022-01-14T01:16:08Z", "author_association": "NONE", "pull_request": null, "body": "Datasette appends the prefix found in the `base_url` setting twice if a `base_url` is set.\r\n\r\nIn the follow asgi example, I'm hosting a custom Datasette instance:\r\n\r\n```python\r\n# asgi.py\r\nimport pathlib\r\nfrom asgi_cors import asgi_cors\r\nfrom channels.routing import URLRouter\r\nfrom django.urls import re_path\r\nfrom datasette.app import Datasette\r\n\r\ndatasette_ = Datasette(\r\n files=[],\r\n settings={\r\n \"base_url\": \"/datasettes/\",\r\n \"plugins\": {}\r\n },\r\n config_dir=pathlib.Path('.'),\r\n)\r\napplication = URLRouter([\r\n re_path(r\"^datasettes/.*\", asgi_cors(datasette_.app(), allow_all=True)),\r\n])\r\n```\r\n\r\nRunning it with:\r\n```shell\r\n$ daphne -p 8002 asgi:application\r\n```\r\n\r\nUsing a simple query on the `_memory` table: \r\n```sql\r\nselect sqlite_version()\r\n```\r\n\r\nhttp://localhost:8002/datasettes/_memory?sql=select+sqlite_version%28%29\r\n\r\nIt renders the following upon inspection:\r\n![image](https://user-images.githubusercontent.com/1001306/149038851-aa842950-126a-467c-9a86-fae13bce6221.png)\r\n\r\nI am using datasette version `0.59.4`", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1590/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1102359726, "node_id": "I_kwDOBm6k_c5BtKyu", "number": 1594, "title": "Add a CLI reference page to the docs, inspired by sqlite-utils", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 3, "created_at": "2022-01-13T20:55:08Z", "updated_at": "2022-01-13T22:28:22Z", "closed_at": "2022-01-13T21:38:48Z", "author_association": "OWNER", "pull_request": null, "body": "Thought of this while posting this comment: https://github.com/simonw/datasette/issues/1591#issuecomment-1012506595\r\n\r\nI added https://sqlite-utils.datasette.io/en/stable/cli-reference.html to `sqlite-utils` in https://github.com/simonw/sqlite-utils/issues/383 and I _really_ like it - it's a page showing the `--help` output of every CLI command for that tool.\r\n\r\nIt's maintained using `cog`. One of the benefits is that I get a free commit history of changes to `--help` at https://github.com/simonw/sqlite-utils/commits/main/docs/cli-reference.rst", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1594/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 1102484126, "node_id": "I_kwDOBm6k_c5BtpKe", "number": 1595, "title": "Release notes for 0.60", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 4, "created_at": "2022-01-13T22:23:14Z", "updated_at": "2022-01-14T01:37:39Z", "closed_at": "2022-01-14T01:37:39Z", "author_association": "OWNER", "pull_request": null, "body": null, "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1595/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 520740741, "node_id": "MDU6SXNzdWU1MjA3NDA3NDE=", "number": 625, "title": "If you apply ?_facet_array=tags then &_facet=tags does nothing", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 13, "created_at": "2019-11-11T04:59:29Z", "updated_at": "2022-01-13T22:26:58Z", "closed_at": "2021-12-16T20:12:22Z", "author_association": "OWNER", "pull_request": null, "body": "Start here: https://v0-30-2.datasette.io/fixtures/facetable?_facet_array=tags\r\n\r\n\"fixtures__facetable__15_rows\"\r\n\r\nNote that `tags` is offered as a suggested facet. But if you click that you get this:\r\n\r\nhttps://v0-30-2.datasette.io/fixtures/facetable?_facet_array=tags&_facet=tags\r\n\r\nThe `_facet=tags` is added to the URL and it's removed from the list of suggested tags... but the facet itself is not displayed:\r\n\r\n\"fixtures__facetable__15_rows\"\r\n\r\nThe `_facet=tags` facet should look like this:\r\n\r\n\"fixtures__facetable__15_rows\"\r\n", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/625/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"} {"id": 991467558, "node_id": "MDU6SXNzdWU5OTE0Njc1NTg=", "number": 1466, "title": "Add Datasette Desktop to installation documentation", "user": {"value": 9599, "label": "simonw"}, "state": "closed", "locked": 0, "assignee": null, "milestone": {"value": 7571612, "label": "Datasette 0.60"}, "comments": 2, "created_at": "2021-09-08T19:41:27Z", "updated_at": "2022-01-13T22:28:28Z", "closed_at": "2022-01-13T21:55:18Z", "author_association": "OWNER", "pull_request": null, "body": "See https://datasette.io/desktop and https://simonwillison.net/2021/Sep/8/datasette-desktop/", "repo": {"value": 107914493, "label": "datasette"}, "type": "issue", "active_lock_reason": null, "performed_via_github_app": null, "reactions": "{\"url\": \"https://api.github.com/repos/simonw/datasette/issues/1466/reactions\", \"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "draft": null, "state_reason": "completed"}