Skip to content

Commit

Permalink
New _nocount=1 option, used to speed up CSVs - closes #1353
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Jun 1, 2021
1 parent 8bde6c5 commit fd368d3
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 5 deletions.
15 changes: 11 additions & 4 deletions datasette/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,12 +263,19 @@ async def get(self, request, db_name, **kwargs):

async def as_csv(self, request, database, hash, **kwargs):
stream = request.args.get("_stream")
# Do not calculate facets:
if not request.args.get("_nofacet"):
# Do not calculate facets or counts:
extra_parameters = [
"{}=1".format(key)
for key in ("_nofacet", "_nocount")
if not request.args.get(key)
]
if extra_parameters:
if not request.query_string:
new_query_string = "_nofacet=1"
new_query_string = "&".join(extra_parameters)
else:
new_query_string = request.query_string + "&_nofacet=1"
new_query_string = (
request.query_string + "&" + "&".join(extra_parameters)
)
new_scope = dict(
request.scope, query_string=new_query_string.encode("latin-1")
)
Expand Down
6 changes: 5 additions & 1 deletion datasette/views/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,11 @@ async def data(
except KeyError:
pass

if count_sql and filtered_table_rows_count is None:
if (
count_sql
and filtered_table_rows_count is None
and not request.args.get("_nocount")
):
try:
count_rows = list(await db.execute(count_sql, from_sql_params))
filtered_table_rows_count = count_rows[0][0]
Expand Down
3 changes: 3 additions & 0 deletions docs/json_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,9 @@ Special table arguments
``?_nofacet=1``
Disable all facets and facet suggestions for this page, including any defined by :ref:`facets_metadata`.

``?_nocount=1``
Disable the ``select count(*)`` query used on this page - a count of ``None`` will be returned instead.

``?_trace=1``
Turns on tracing for this page: SQL queries executed during the request will
be gathered and included in the response, either in a new ``"_traces"`` key
Expand Down
9 changes: 9 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1683,6 +1683,15 @@ def test_nofacet(app_client, nofacet):
assert response.json["facet_results"] != {}


@pytest.mark.parametrize("nocount,expected_count", ((True, None), (False, 15)))
def test_nocount(app_client, nocount, expected_count):
path = "/fixtures/facetable.json"
if nocount:
path += "?_nocount=1"
response = app_client.get(path)
assert response.json["filtered_table_rows_count"] == expected_count


def test_expand_labels(app_client):
response = app_client.get(
"/fixtures/facetable.json?_shape=object&_labels=1&_size=2"
Expand Down
6 changes: 6 additions & 0 deletions tests/test_csv.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,3 +175,9 @@ def test_table_csv_stream_does_not_calculate_facets(app_client):
response = app_client.get("/fixtures/simple_primary_key.csv?_trace=1")
soup = Soup(response.text, "html.parser")
assert "select content, count(*) as n" not in soup.find("pre").text


def test_table_csv_stream_does_not_calculate_counts(app_client):
response = app_client.get("/fixtures/simple_primary_key.csv?_trace=1")
soup = Soup(response.text, "html.parser")
assert "select count(*)" not in soup.find("pre").text

0 comments on commit fd368d3

Please sign in to comment.