Commit graph

1,249 commits

Author SHA1 Message Date
Simon Willison
bb59c61c9f Request-scoped permission check cache
Adds a per-request cache for permission check results, plus wiring that
resolves action permissions in bulk before plugin hooks need them:

- New _permission_check_cache contextvar, set to a fresh dict for each
  request by DatasetteRouter and reset when the request ends. Keys
  include the full serialized actor, so actors differing in any field
  (e.g. token restrictions) never share entries. SkipPermissions mode
  bypasses the cache entirely.
- datasette.allowed_many() now consults the cache and stores its
  results there, so repeated datasette.allowed() checks within one
  request resolve without further SQL.
- Table pages resolve all registered table-level actions against the
  current table and all database-level actions against its database
  (database pages likewise) in batched queries before invoking the
  table_actions/database_actions plugin hooks - allowed() calls made
  inside those hooks are then served from the cache with no plugin
  changes required. Actions with no permission rules from any plugin
  are resolved to False without touching the database.

Benchmarks (benchmarks/) with a simulated 12-plugin ecosystem making
18 checks per table page show 34 -> 13 internal-DB queries per page;
with 2ms-per-query internal DB latency (modelling Datasette Cloud)
table page time drops from 77.9ms to 27.6ms - the caching layer
accounts for ~91% of that improvement over allowed_many() alone.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-12 13:11:17 -07:00
Simon Willison
88878b4184 datasette.allowed_many() method 2026-06-12 12:51:40 -07:00
Simon Willison
fa86ac7b11
Clearer examples and descriptions for JSON API extras (#2773)
Review of the generated ?_extra= documentation found several extras
with no example output or with examples that needed explanation:

- extras: now shows an abbreviated example of the toggle list and has
  a clearer description (which also improves the live API output)
- set_column_type_ui: example of the shape seen with set-column-type
  permission, plus a note that it is null otherwise
- column_types: live example generated from a table with an assigned
  column type instead of an empty {}
- metadata: live table example now demonstrates a table description
  and column descriptions; row and query examples gained explanatory
  notes
- expandable_columns, foreign_key_tables, facets_timed_out, next_url,
  renderers: notes explaining the shape of their output

Also added docs_note cross-references to the relevant documentation:
facets, pagination, render_cell and register_output_renderer plugin
hooks, column type configuration and API, metadata, custom templates,
permissions and foreign key label expansion. foreign_key_tables is
now flagged as potentially executing additional queries.

https://claude.ai/code/session_01EfjBe6E817m9XNFW7EX3Vm

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-11 19:41:24 -07:00
Simon Willison
1d4212122e Add release date for 1.0a33 2026-06-11 10:36:16 -07:00
Simon Willison
993169ae49 Release 1.0a33
Refs #2735, #2677, #2680, #2711, #2756, #2761, #2768, #2754
2026-06-11 08:24:37 -07:00
Simon Willison
bbf0424c45 Changelog for row/query extras and related fixes
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:51:25 -07:00
Simon Willison
b635dc53f4 Make filters, actions and display_rows extras internal
These three extras return values that exist for the HTML templates -
a Filters instance, an async function and markupsafe/sqlite3.Row data
- so requesting them on a .json page returned a 500 serialization
error, while the generated documentation and ?_extra=extras both
advertised them as API surface. They are now public=False: ignored
like any unknown name on JSON requests, omitted from the docs and the
extras list, and still resolved for the HTML view via the new
include_internal flag on ExtraRegistry.resolve().

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 22:50:44 -07:00
Simon Willison
4d6daa175a Add row and query JSON extras 2026-06-09 02:56:27 -07:00
Simon Willison
0fa872d438 Add debug and request JSON extra examples 2026-06-08 21:20:06 -07:00
Simon Willison
22f80b8196 Clarify render_cell JSON extra example 2026-06-08 21:13:53 -07:00
Simon Willison
79c8aff31d Add generated examples for table JSON extras 2026-06-08 21:10:58 -07:00
Simon Willison
111eeaf370 Document table JSON extras from metadata 2026-06-08 20:56:00 -07:00
Simon Willison
6eaa9e3199
Web UI to edit and delete stored queries (#2764)
* Add web UI to edit and delete stored queries

Stored query pages now offer Edit and Delete actions in the query
actions menu, gated by the update-query and delete-query permissions.

- New QueryEditView (GET/POST at /<db>/<query>/-/edit) renders a
  pre-filled form for editing a query's title, description, SQL and
  privacy, reusing the create-query analysis UI. Changing the SQL still
  requires execute-sql; metadata-only edits do not.
- QueryDeleteView gains a GET confirmation page and HTML form POST that
  redirects to the query list, while keeping the existing JSON API.
- New default query_actions hook adds the Edit/Delete links for stored
  (non-config, non-trusted) queries the actor is allowed to manage.

Permission semantics (already enforced by default_query_permissions_sql)
are surfaced in the UI: owners can always edit/delete their queries;
non-private queries can be edited/deleted by any actor with the relevant
permission; private queries remain owner-only.

Shared the create-query form styles into _query_form_styles.html so the
edit form can reuse them.

Animated demo: https://github.com/simonw/datasette/pull/2764#issuecomment-4655694668

Closes #2760

https://claude.ai/code/session_019GU9g3pZAERukLKYNa4uAL
2026-06-08 20:19:47 -07:00
Simon Willison
911954347e Release 1.0a32
Refs #2757, #2759, #2762, #2763
2026-05-31 16:21:24 -07:00
Simon Willison
b1f3e4368c
Fixes for SQL write with RETURNING (#2763)
* Fix for execute write returning, closes #2762
* Fix stored write returning rowcount message
* Add configurable execute_write returning limit
* Return rows/truncated from execute query if it used RETURNING
* INSERT ... RETURNING shows rows in /-/execute-write
* Skip RETURNING tests if SQLite version does not support it

Screenshot: https://github.com/simonw/datasette/issues/2762#issuecomment-4588111545
2026-05-31 16:15:34 -07:00
Simon Willison
c1476a48d8 Release 1.0a31
Refs #2712, #2735, #2742, #2743, #2747, #2748
2026-05-28 20:29:57 -07:00
Simon Willison
72cf476d1d Tidied up release notes ready to ship
Refs #2741, #2749
2026-05-28 20:28:24 -07:00
Simon Willison
52729faa54 /<database>/-/query.json and changelog docs 2026-05-28 20:01:56 -07:00
Simon Willison
6a998610ee
datasette inspect now counts 10,000+ tables correctly (#2752)
Closes #2712

Refs https://github.com/simonw/datasette/pull/2721#issuecomment-4568966383
2026-05-28 15:52:51 -07:00
Simon Willison
74324cb849 Improved docs for user-facing SQL query pages
- /database-name/-/execute-write
- /-/queries
2026-05-28 15:46:27 -07:00
Simon Willison
b2b20b36c5 Document write SQL analyzer restrictions
Expand the unreleased changelog with the deny-by-default operation analysis model, SQL function handling, and the VACUUM and virtual/shadow table restrictions for user-supplied write SQL.

Clarify the /-/execute-write JSON API documentation with the same restrictions and DDL permission requirements.
2026-05-28 10:24:40 -07:00
Simon Willison
51dab16149 Allow SQL functions in SQL write queries
Closes #2751
2026-05-28 10:22:28 -07:00
Simon Willison
0c5053cdf6 Docs for /<database>/-/execute-write JSON API
Closes #2750, refs #2742
2026-05-27 17:26:50 -07:00
Simon Willison
b1289a73f9 stored_queries.StoredQuery dataclass 2026-05-26 16:51:00 -07:00
Simon Willison
90e19a7d58 Docs for datasette methods for queries
Refs https://github.com/simonw/datasette/pull/2741#issuecomment-4549824373
2026-05-26 16:33:36 -07:00
Simon Willison
2eb307b8c6 Changelog updates for queries branch
Refs #2735, #2742
2026-05-26 16:10:05 -07:00
Simon Willison
3c29b002ca Do not document unstable JSON APIs for stored queries 2026-05-26 16:07:53 -07:00
Simon Willison
cef52b1ffc Break up giant views/database.py into smaller modules 2026-05-26 16:06:14 -07:00
Simon Willison
7214cc3761 Remove obsolete label 2026-05-26 15:52:44 -07:00
Simon Willison
58e2e3a8ab Ran cog 2026-05-26 15:43:34 -07:00
Simon Willison
02a1468f1b Renamed canned queries to queries / stored queries in docs
And a few renames in code and YAML as well.
2026-05-26 15:17:51 -07:00
Simon Willison
56b14f37d5 The stored queries do not live in that DB 2026-05-26 15:16:18 -07:00
Simon Willison
2f73869c09 Document that canned_queries() has been removed 2026-05-26 15:09:48 -07:00
Simon Willison
b1029acc68 top_canned_query is now top_stored_query, closes #2747 2026-05-26 15:05:41 -07:00
Simon Willison
4bf1c4b065 Rename canned queries to queries/stored queries in docs 2026-05-26 14:54:35 -07:00
Simon Willison
24887004cf Rename insert-query to store-query
Also queries/insert to queries/store

Refs https://github.com/simonw/datasette/pull/2741#issuecomment-4549103663
2026-05-26 14:51:59 -07:00
Simon Willison
6033bf8e40 Merge branch 'main' into queries 2026-05-26 13:51:51 -07:00
Simon Willison
1ac4265ffd Require permissions for untrusted stored query execution, refs #2735 2026-05-26 12:12:59 -07:00
Simon Willison
4a1a4d7807 Query is_trusted and is_private properties
Refs https://github.com/simonw/datasette/issues/2735#issuecomment-4547270516

Diff explanation: https://gist.github.com/simonw/1e4de6c4b041a51968eb273ee96dec1f
2026-05-26 11:59:49 -07:00
Simon Willison
f1dd86ebfb Tweak URL designs of new endpoints 2026-05-25 14:05:26 -07:00
Simon Willison
1f7c26ffea Refactor to share JS/HTML between execute and execute-write
Refs #2742
2026-05-25 12:45:42 -07:00
Simon Willison
de55a76d40
Fix 500 error when accessing query page without ?sql= parameter (#2744)
Closes #2743
2026-05-25 12:33:57 -07:00
Simon Willison
e1261442c0 Update parameters/query operations as user edits the write query
Refs #2742
2026-05-25 12:09:52 -07:00
Simon Willison
6eee6c81e8 Add global query browser
Refs #2735
2026-05-25 10:24:42 -07:00
Simon Willison
4a70b89355 Add cursor-paginated query browser
Refs #2735
2026-05-25 10:11:46 -07:00
Simon Willison
539ff9ddfc Drop query publication check from docs
Refs #2735
2026-05-25 09:49:21 -07:00
Simon Willison
2d07c3b99e Ran cog 2026-05-25 09:47:12 -07:00
Simon Willison
e62a5ea337 Rename query publication flag
Refs #2735
2026-05-25 09:46:39 -07:00
Simon Willison
e0d39ba69f Store query options as JSON
Refs #2735
2026-05-25 09:41:32 -07:00
Simon Willison
ef43c10388 Add arbitrary write SQL execution page
Refs #2735
2026-05-25 08:30:49 -07:00