Skip to content

Commit

Permalink
First working version of writable canned queries, refs #698
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Jun 1, 2020
1 parent dfdbdf3 commit 5b252a2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 7 deletions.
6 changes: 6 additions & 0 deletions datasette/static/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,9 @@ p.zero-results {
.type-float, .type-int {
color: #666;
}

.success {
padding: 1em;
border: 1px solid green;
background-color: #c7fbc7;
}
10 changes: 8 additions & 2 deletions datasette/templates/query.html
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,12 @@
{% endblock %}

{% block content %}

<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_color(database) }}">{{ metadata.title or database }}</h1>

{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}

<form class="sql" action="{{ database_url(database) }}{% if canned_query %}/{{ canned_query }}{% endif %}" method="get">
<form class="sql" action="{{ database_url(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 %} <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></h3>
{% if not hide_sql %}
{% if editable and config.allow_sql %}
Expand Down Expand Up @@ -74,7 +75,12 @@ <h3>Query parameters</h3>
</tbody>
</table>
{% else %}
<p class="zero-results">0 results</p>
{% if success_message %}
<p class="success">{{ success_message }}</p>
{% endif %}
{% if not canned_write %}
<p class="zero-results">0 results</p>
{% endif %}
{% endif %}

{% include "_codemirror_foot.html" %}
Expand Down
46 changes: 41 additions & 5 deletions datasette/views/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,16 @@ async def data(
canned_query=None,
metadata=None,
_size=None,
named_parameters=None,
write=False,
):
params = {key: request.args.get(key) for key in request.args}
if "sql" in params:
params.pop("sql")
if "_shape" in params:
params.pop("_shape")
# Extract any :named parameters
named_parameters = self.re_named_parameter.findall(sql)
named_parameters = named_parameters or self.re_named_parameter.findall(sql)
named_parameter_values = {
named_parameter: params.get(named_parameter) or ""
for named_parameter in named_parameters
Expand All @@ -129,12 +131,46 @@ async def data(
extra_args["custom_time_limit"] = int(params["_timelimit"])
if _size:
extra_args["page_size"] = _size
results = await self.ds.execute(
database, sql, params, truncate=True, **extra_args
)
columns = [r[0] for r in results.description]

templates = ["query-{}.html".format(to_css_class(database)), "query.html"]

# Execute query - as write or as read
if write:
if request.method == "POST":
params = await request.post_vars()
write_ok = await self.ds.databases[database].execute_write(
sql, params, block=True
)
return self.redirect(request, request.path + '?_success=Query+executed_successfully')
else:
async def extra_template():
return {
"request": request,
"path_with_added_args": path_with_added_args,
"path_with_removed_args": path_with_removed_args,
"named_parameter_values": named_parameter_values,
"canned_query": canned_query,
"success_message": request.raw_args.get("_success") or "",
"canned_write": True,
}

return (
{
"database": database,
"rows": [],
"truncated": False,
"columns": [],
"query": {"sql": sql, "params": params},
},
extra_template,
templates,
)
else: # Not a write
results = await self.ds.execute(
database, sql, params, truncate=True, **extra_args
)
columns = [r[0] for r in results.description]

if canned_query:
templates.insert(
0,
Expand Down
18 changes: 18 additions & 0 deletions datasette/views/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,22 @@ async def display_columns_and_rows(
class TableView(RowTableShared):
name = "table"

async def post(self, request, db_name, table_and_format):
# Handle POST to a canned query
canned_query = self.ds.get_canned_query(db_name, table_and_format)
assert canned_query, "You may only POST to a canned query"
return await QueryView(self.ds).data(
request,
db_name,
None,
canned_query["sql"],
metadata=canned_query,
editable=False,
canned_query=table_and_format,
named_parameters=canned_query.get("params"),
write=bool(canned_query.get("write")),
)

async def data(
self,
request,
Expand All @@ -241,6 +257,8 @@ async def data(
metadata=canned_query,
editable=False,
canned_query=table,
named_parameters=canned_query.get("params"),
write=bool(canned_query.get("write")),
)

db = self.ds.databases[database]
Expand Down

0 comments on commit 5b252a2

Please sign in to comment.