mirror of
https://github.com/simonw/datasette.git
synced 2026-05-27 12:34:37 +02:00
Merge branch 'main' into queries
This commit is contained in:
commit
6033bf8e40
5 changed files with 50 additions and 24 deletions
|
|
@ -47,14 +47,14 @@
|
|||
{% if not hide_sql %}
|
||||
{% if editable and allow_execute_sql %}
|
||||
<p class="sql-editor"><textarea id="sql-editor" name="sql"{% if query and query.sql %} style="height: {{ query.sql.split("\n")|length + 2 }}em"{% endif %}
|
||||
>{% if query and query.sql %}{{ query.sql }}{% else %}select * from {{ tables[0].name|escape_sqlite }}{% endif %}</textarea></p>
|
||||
>{% if query and query.sql %}{{ query.sql }}{% elif tables %}select * from {{ tables[0].name|escape_sqlite }}{% endif %}</textarea></p>
|
||||
{% else %}
|
||||
<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 %}"
|
||||
value="{% if query and query.sql %}{{ query.sql }}{% elif tables %}select * from {{ tables[0].name|escape_sqlite }}{% endif %}"
|
||||
>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
|
|
|
|||
|
|
@ -1776,7 +1776,7 @@ class QueryView(View):
|
|||
named_parameters = []
|
||||
if canned_query and canned_query.get("params"):
|
||||
named_parameters = canned_query["params"]
|
||||
if not named_parameters:
|
||||
if not named_parameters and sql:
|
||||
named_parameters = derive_named_parameters(sql)
|
||||
named_parameter_values = {
|
||||
named_parameter: params.get(named_parameter) or ""
|
||||
|
|
@ -1801,7 +1801,7 @@ class QueryView(View):
|
|||
|
||||
params_for_query = params
|
||||
|
||||
if not canned_query_write:
|
||||
if sql and not canned_query_write:
|
||||
try:
|
||||
if not canned_query:
|
||||
# For regular queries we only allow SELECT, plus other rules
|
||||
|
|
@ -1845,6 +1845,8 @@ class QueryView(View):
|
|||
|
||||
# Handle formats from plugins
|
||||
if format_ == "csv":
|
||||
if not sql:
|
||||
raise DatasetteError("?sql= is required", status=400)
|
||||
|
||||
async def fetch_data_for_csv(request, _next=None):
|
||||
results = await db.execute(sql, params, truncate=True)
|
||||
|
|
@ -1978,25 +1980,26 @@ class QueryView(View):
|
|||
# - No magic parameters, so no :_ in the SQL string
|
||||
edit_sql_url = None
|
||||
is_validated_sql = False
|
||||
try:
|
||||
validate_sql_select(sql)
|
||||
is_validated_sql = True
|
||||
except InvalidSql:
|
||||
pass
|
||||
if allow_execute_sql and is_validated_sql and ":_" not in sql:
|
||||
edit_sql_url = (
|
||||
datasette.urls.database(database)
|
||||
+ "/-/query"
|
||||
+ "?"
|
||||
+ urlencode(
|
||||
{
|
||||
**{
|
||||
"sql": sql,
|
||||
},
|
||||
**named_parameter_values,
|
||||
}
|
||||
if sql:
|
||||
try:
|
||||
validate_sql_select(sql)
|
||||
is_validated_sql = True
|
||||
except InvalidSql:
|
||||
pass
|
||||
if allow_execute_sql and is_validated_sql and ":_" not in sql:
|
||||
edit_sql_url = (
|
||||
datasette.urls.database(database)
|
||||
+ "/-/query"
|
||||
+ "?"
|
||||
+ urlencode(
|
||||
{
|
||||
**{
|
||||
"sql": sql,
|
||||
},
|
||||
**named_parameter_values,
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
save_query_url = None
|
||||
if (
|
||||
not canned_query
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@
|
|||
Changelog
|
||||
=========
|
||||
|
||||
.. _v1_0_unreleased:
|
||||
|
||||
Unreleased
|
||||
----------
|
||||
|
||||
- Fixed a bug where visiting ``/<database>/-/query`` without a ``?sql=`` parameter returned a 500 error. (:issue:`2743`)
|
||||
|
||||
.. _v1_0_a30:
|
||||
|
||||
1.0a30 (2026-05-24)
|
||||
|
|
|
|||
|
|
@ -382,8 +382,8 @@ def view_actions(datasette, database, view, actor):
|
|||
|
||||
@hookimpl
|
||||
def query_actions(datasette, database, query_name, sql):
|
||||
# Don't explain an explain
|
||||
if sql.lower().startswith("explain"):
|
||||
# Don't explain an explain (or a missing query)
|
||||
if not sql or sql.lower().startswith("explain"):
|
||||
return
|
||||
return [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -239,6 +239,22 @@ def test_query_page_truncates():
|
|||
]
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_page_with_no_sql(ds_client):
|
||||
# https://github.com/simonw/datasette/issues/2743
|
||||
response = await ds_client.get("/fixtures/-/query")
|
||||
assert response.status_code == 200
|
||||
assert '<textarea id="sql-editor" name="sql"' in response.text
|
||||
assert 'class="rows-and-columns"' not in response.text
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_query_csv_with_no_sql_is_400(ds_client):
|
||||
# https://github.com/simonw/datasette/issues/2743
|
||||
response = await ds_client.get("/fixtures/-/query.csv")
|
||||
assert response.status_code == 400
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize(
|
||||
"path,expected_classes",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue