From c980234c41a9bc7a188f17c7f07e48ef1a7640a7 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sat, 23 May 2026 21:00:04 -0700 Subject: [PATCH] JumpSQL(database=) parameter Refs https://github.com/simonw/datasette/pull/2732#issuecomment-4527304912 --- datasette/jump.py | 3 +- datasette/views/special.py | 76 ++++++++++++++---- docs/changelog.rst | 2 +- docs/plugin_hooks.rst | 10 ++- tests/test_jump.py | 153 +++++++++++++++++++++++++++++++++++++ 5 files changed, 225 insertions(+), 19 deletions(-) diff --git a/datasette/jump.py b/datasette/jump.py index 17c86bfd..d138e827 100644 --- a/datasette/jump.py +++ b/datasette/jump.py @@ -9,6 +9,7 @@ from typing import Any class JumpSQL: sql: str params: dict[str, Any] | None = None + database: str | None = None @classmethod def menu_item( @@ -50,7 +51,7 @@ _PARAM_RE = re.compile(r"(? 100 - if truncated: + db = ( + self.ds.get_internal_database() + if database_name is None + else self.ds.get_database(database_name) + ) + result = await db.execute(sql, params) + return list(result.rows) + + async def get(self, request): + q = request.args.get("q", "").strip() + terms = q.split() + pattern = "%" + "%".join(terms) + "%" if terms else "%" + fragments = await self._fragments(request) + + fragments_by_database = {} + for index, fragment in enumerate(fragments): + fragments_by_database.setdefault(fragment.database, []).append( + (index, fragment) + ) + + rows = [] + truncated = False + for database_name, indexed_fragments in fragments_by_database.items(): + database_rows = await self._rows_for_database( + database_name, indexed_fragments, q, pattern + ) + if len(database_rows) > 100: + truncated = True + database_rows = database_rows[:100] + rows.extend(database_rows) + rows.sort(key=lambda row: self._sort_key(row, q)) + + if len(rows) > 100: + truncated = True rows = rows[:100] matches = [] diff --git a/docs/changelog.rst b/docs/changelog.rst index 84015b46..a51684ab 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -14,7 +14,7 @@ Unreleased - Fixed a Safari bug with the table search mechanism triggered by pressing ``/``. (:issue:`2724`) - New "Jump to..." menu item, always visible, for triggering the previously undocumented ``/`` menu. (:issue:`2725`) - The ``/`` jump-to search interface now covers databases, views, canned queries and plugin-provided items in addition to tables. The endpoint backing it has been renamed from ``/-/tables`` to ``/-/jump``. -- New :ref:`plugin_hook_jump_items_sql` plugin hook, allowing plugins to contribute additional items to the jump-to menu by returning SQL that queries the internal catalog. Each row returned by this hook includes a ``url`` value, which can be a string starting with ``/`` or a JSON object describing a call to one of the :ref:`internals_datasette_urls` methods. +- New :ref:`plugin_hook_jump_items_sql` plugin hook, allowing plugins to contribute additional items to the jump-to menu by returning SQL. ``JumpSQL`` queries run against Datasette's internal database by default, or can target another database using the optional ``database=`` argument. Datasette groups these queries by database and executes one ``UNION ALL`` query for each database. Each row returned by this hook includes a ``url`` value, which can be a string starting with ``/`` or a JSON object describing a call to one of the :ref:`internals_datasette_urls` methods. - ``datasette.jump.JumpSQL.menu_item()`` is a shortcut for adding individual jump menu items that are not backed by resources in the internal catalog. - New :ref:`javascript_plugins_makeJumpSections` JavaScript plugin hook, allowing plugins to add custom blank-state sections to the jump-to menu before the user has typed a query. - Jump menu results now show their ``type`` as a category label, and can show optional longer ``description`` text for individual results. diff --git a/docs/plugin_hooks.rst b/docs/plugin_hooks.rst index 4d8e980f..e2789112 100644 --- a/docs/plugin_hooks.rst +++ b/docs/plugin_hooks.rst @@ -1884,7 +1884,7 @@ Examples: `datasette-search-all