Skip to content

Commit

Permalink
New hide_sql canned query option, refs #1422
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Aug 7, 2021
1 parent b7037f5 commit 66e143c
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 14 deletions.
14 changes: 10 additions & 4 deletions datasette/templates/query.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ <h1 style="padding-left: 10px; border-left: 10px solid #{{ database_color(databa
{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}

<form class="sql" action="{{ urls.database(database) }}{% if canned_query %}/{{ canned_query }}{% endif %}" method="{% if canned_write %}post{% else %}get{% endif %}">
<h3>Custom SQL query{% if display_rows %} returning {% if truncated %}more than {% endif %}{{ "{:,}".format(display_rows|length) }} row{% if display_rows|length == 1 %}{% else %}s{% endif %}{% endif %}{% if not query_error %} <span class="show-hide-sql">{% if hide_sql %}(<a href="{{ path_with_removed_args(request, {'_hide_sql': '1'}) }}">show</a>){% else %}(<a href="{{ path_with_added_args(request, {'_hide_sql': '1'}) }}">hide</a>){% endif %}</span>{% endif %}</h3>
<h3>Custom SQL query{% if display_rows %} returning {% if truncated %}more than {% endif %}{{ "{:,}".format(display_rows|length) }} row{% if display_rows|length == 1 %}{% else %}s{% endif %}{% endif %}{% if not query_error %}
<span class="show-hide-sql">(<a href="{{ show_hide_link }}">{{ show_hide_text }}</a>)</span>
{% endif %}</h3>
{% if error %}
<p class="message-error">{{ error }}</p>
{% endif %}
Expand All @@ -44,8 +46,11 @@ <h3>Custom SQL query{% if display_rows %} returning {% if truncated %}more than
<pre id="sql-query">{% if query %}{{ query.sql }}{% endif %}</pre>
{% endif %}
{% else %}
{% if not canned_query %}<input type="hidden" name="sql" value="{% if query and query.sql %}{{ query.sql }}{% else %}select * from {{ tables[0].name|escape_sqlite }}{% endif %}">{% endif %}
<input type="hidden" name="_hide_sql" value="1">
{% if not canned_query %}
<input type="hidden" name="sql"
value="{% if query and query.sql %}{{ query.sql }}{% else %}select * from {{ tables[0].name|escape_sqlite }}{% endif %}"
>
{% endif %}
{% endif %}
{% if named_parameter_values %}
<h3>Query parameters</h3>
Expand All @@ -54,9 +59,10 @@ <h3>Query parameters</h3>
{% endfor %}
{% endif %}
<p>
<button id="sql-format" type="button" hidden>Format SQL</button>
{% if not hide_sql %}<button id="sql-format" type="button" hidden>Format SQL</button>{% endif %}
{% if canned_write %}<input type="hidden" name="csrftoken" value="{{ csrftoken() }}">{% endif %}
<input type="submit" value="Run SQL">
{{ show_hide_hidden }}
{% if canned_query and edit_sql_url %}<a href="{{ edit_sql_url }}" class="canned-query-edit-sql">Edit SQL</a>{% endif %}
</p>
</form>
Expand Down
32 changes: 29 additions & 3 deletions datasette/views/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from markupsafe import Markup, escape
from urllib.parse import parse_qsl, urlencode

import markupsafe

from datasette.utils import (
await_me_maybe,
check_visibility,
Expand Down Expand Up @@ -415,6 +417,29 @@ async def extra_template():
}
)
)

show_hide_hidden = ""
if metadata.get("hide_sql"):
if bool(params.get("_show_sql")):
show_hide_link = path_with_removed_args(request, {"_show_sql"})
show_hide_text = "hide"
show_hide_hidden = (
'<input type="hidden" name="_show_sql" value="1">'
)
else:
show_hide_link = path_with_added_args(request, {"_show_sql": 1})
show_hide_text = "show"
else:
if bool(params.get("_hide_sql")):
show_hide_link = path_with_removed_args(request, {"_hide_sql"})
show_hide_text = "show"
show_hide_hidden = (
'<input type="hidden" name="_hide_sql" value="1">'
)
else:
show_hide_link = path_with_added_args(request, {"_hide_sql": 1})
show_hide_text = "hide"
hide_sql = show_hide_text == "show"
return {
"display_rows": display_rows,
"custom_sql": True,
Expand All @@ -425,9 +450,10 @@ async def extra_template():
"metadata": metadata,
"config": self.ds.config_dict(),
"request": request,
"path_with_added_args": path_with_added_args,
"path_with_removed_args": path_with_removed_args,
"hide_sql": "_hide_sql" in params,
"show_hide_link": show_hide_link,
"show_hide_text": show_hide_text,
"show_hide_hidden": markupsafe.Markup(show_hide_hidden),
"hide_sql": hide_sql,
}

return (
Expand Down
2 changes: 1 addition & 1 deletion docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ The main focus of this release is a major upgrade to the :ref:`plugin_register_o
* Visually distinguish float and integer columns - useful for figuring out why order-by-column might be returning unexpected results. (:issue:`729`)
* The :ref:`internals_request`, which is passed to several plugin hooks, is now documented. (:issue:`706`)
* New ``metadata.json`` option for setting a custom default page size for specific tables and views, see :ref:`metadata_page_size`. (:issue:`751`)
* Canned queries can now be configured with a default URL fragment hash, useful when working with plugins such as `datasette-vega <https://github.com/simonw/datasette-vega>`__, see :ref:`canned_queries_default_fragment`. (:issue:`706`)
* Canned queries can now be configured with a default URL fragment hash, useful when working with plugins such as `datasette-vega <https://github.com/simonw/datasette-vega>`__, see :ref:`canned_queries_options`. (:issue:`706`)
* Fixed a bug in ``datasette publish`` when running on operating systems where the ``/tmp`` directory lives in a different volume, using a backport of the Python 3.8 ``shutil.copytree()`` function. (:issue:`744`)
* Every plugin hook is now covered by the unit tests, and a new unit test checks that each plugin hook has at least one corresponding test. (:issue:`771`, :issue:`773`)

Expand Down
25 changes: 20 additions & 5 deletions docs/sql_queries.rst
Original file line number Diff line number Diff line change
Expand Up @@ -187,14 +187,28 @@ You can alternatively provide an explicit list of named parameters using the ``"
order by neighborhood
title: Search neighborhoods
.. _canned_queries_default_fragment:
.. _canned_queries_options:

Setting a default fragment
~~~~~~~~~~~~~~~~~~~~~~~~~~
Additional canned query options
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Additional options can be specified for canned queries in the YAML or JSON configuration.

hide_sql
++++++++

Canned queries default to displaying their SQL query at the top of the page. If the query is extremely long you may want to hide it by default, with a "show" link that can be used to make it visible.

Add the ``"hide_sql": true`` option to hide the SQL query by default.

fragment
++++++++

Some plugins, such as `datasette-vega <https://github.com/simonw/datasette-vega>`__, can be configured by including additional data in the fragment hash of the URL - the bit that comes after a ``#`` symbol.

You can set a default fragment hash that will be included in the link to the canned query from the database index page using the ``"fragment"`` key:
You can set a default fragment hash that will be included in the link to the canned query from the database index page using the ``"fragment"`` key.

This example demonstrates both ``fragment`` and ``hide_sql``:

.. code-block:: json
Expand All @@ -204,7 +218,8 @@ You can set a default fragment hash that will be included in the link to the can
"queries": {
"neighborhood_search": {
"sql": "select neighborhood, facet_cities.name, state\nfrom facetable join facet_cities on facetable.city_id = facet_cities.id\nwhere neighborhood like '%' || :text || '%' order by neighborhood;",
"fragment": "fragment-goes-here"
"fragment": "fragment-goes-here",
"hide_sql": true
}
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@ def generate_sortable_rows(num):
"title": "Search neighborhoods",
"description_html": "<b>Demonstrating</b> simple like search",
"fragment": "fragment-goes-here",
"hide_sql": True,
},
},
}
Expand Down
51 changes: 50 additions & 1 deletion tests/test_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -1241,14 +1241,63 @@ def test_show_hide_sql_query(app_client):
def test_canned_query_with_hide_has_no_hidden_sql(app_client):
# For a canned query the show/hide should NOT have a hidden SQL field
# https://github.com/simonw/datasette/issues/1411
response = app_client.get("/fixtures/neighborhood_search?_hide_sql=1")
response = app_client.get("/fixtures/pragma_cache_size?_hide_sql=1")
soup = Soup(response.body, "html.parser")
hiddens = soup.find("form").select("input[type=hidden]")
assert [
("_hide_sql", "1"),
] == [(hidden["name"], hidden["value"]) for hidden in hiddens]


@pytest.mark.parametrize(
"hide_sql,querystring,expected_hidden,expected_show_hide_link,expected_show_hide_text",
(
(False, "", None, "/_memory/one?_hide_sql=1", "hide"),
(False, "?_hide_sql=1", "_hide_sql", "/_memory/one", "show"),
(True, "", None, "/_memory/one?_show_sql=1", "show"),
(True, "?_show_sql=1", "_show_sql", "/_memory/one", "hide"),
),
)
def test_canned_query_show_hide_metadata_option(
hide_sql,
querystring,
expected_hidden,
expected_show_hide_link,
expected_show_hide_text,
):
with make_app_client(
metadata={
"databases": {
"_memory": {
"queries": {
"one": {
"sql": "select 1 + 1",
"hide_sql": hide_sql,
}
}
}
}
},
memory=True,
) as client:
expected_show_hide_fragment = '(<a href="{}">{}</a>)'.format(
expected_show_hide_link, expected_show_hide_text
)
response = client.get("/_memory/one" + querystring)
html = response.text
show_hide_fragment = html.split('<span class="show-hide-sql">')[1].split(
"</span>"
)[0]
assert show_hide_fragment == expected_show_hide_fragment
if expected_hidden:
assert (
'<input type="hidden" name="{}" value="1">'.format(expected_hidden)
in html
)
else:
assert '<input type="hidden" ' not in html


def test_extra_where_clauses(app_client):
response = app_client.get(
"/fixtures/facetable?_where=neighborhood='Dogpatch'&_where=city_id=1"
Expand Down

0 comments on commit 66e143c

Please sign in to comment.