home / github / issue_comments

Menu
  • Search all tables
  • GraphQL API

issue_comments: 1399145981

This data as json

html_url issue_url id node_id user created_at updated_at author_association body reactions issue performed_via_github_app
https://github.com/simonw/datasette/issues/262#issuecomment-1399145981 https://api.github.com/repos/simonw/datasette/issues/262 1399145981 IC_kwDOBm6k_c5TZUX9 9599 2023-01-21T01:56:52Z 2023-01-21T01:56:52Z OWNER

Got first prototype working using asyncinject and it's pretty nice: ```diff diff --git a/datasette/views/table.py b/datasette/views/table.py index ad45ecd3..c8690b22 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -2,6 +2,7 @@ import asyncio import itertools import json

+from asyncinject import Registry import markupsafe

from datasette.plugins import pm @@ -538,57 +539,60 @@ class TableView(DataView): # Execute the main query! results = await db.execute(sql, params, truncate=True, **extra_args)

  • Calculate the total count for this query

  • count = None
  • if (
  • not db.is_mutable
  • and self.ds.inspect_data
  • and count_sql == f"select count(*) from {table_name} "
  • ):
  • We can use a previously cached table row count

  • try:
  • count = self.ds.inspect_data[database_name]["tables"][table_name][
  • "count"
  • ]
  • except KeyError:
  • pass

  • Otherwise run a select count(*) ...

  • if count_sql and count is None and not nocount:
  • try:
  • count_rows = list(await db.execute(count_sql, from_sql_params))
  • count = count_rows[0][0]
  • except QueryInterrupted:
  • pass

  • Faceting

  • if not self.ds.setting("allow_facet") and any(
  • arg.startswith("_facet") for arg in request.args
  • ):
  • raise BadRequest("_facet= is not allowed")
  • Resolve extras

  • extras = _get_extras(request)
  • if request.args.getlist("_facet"):
  • extras.add("facet_results")

  • pylint: disable=no-member

  • facet_classes = list(
  • itertools.chain.from_iterable(pm.hook.register_facet_classes())
  • )
  • facet_results = {}
  • facets_timed_out = []
  • facet_instances = []
  • for klass in facet_classes:
  • facet_instances.append(
  • klass(
  • self.ds,
  • request,
  • database_name,
  • sql=sql_no_order_no_limit,
  • params=params,
  • table=table_name,
  • metadata=table_metadata,
  • row_count=count,
  • )
  • async def extra_count():
  • Calculate the total count for this query

  • count = None
  • if (
  • not db.is_mutable
  • and self.ds.inspect_data
  • and count_sql == f"select count(*) from {table_name} "
  • ):
  • We can use a previously cached table row count

  • try:
  • count = self.ds.inspect_data[database_name]["tables"][table_name][
  • "count"
  • ]
  • except KeyError:
  • pass +
  • Otherwise run a select count(*) ...

  • if count_sql and count is None and not nocount:
  • try:
  • count_rows = list(await db.execute(count_sql, from_sql_params))
  • count = count_rows[0][0]
  • except QueryInterrupted:
  • pass
  • return count +
  • async def facet_instances(extra_count):
  • facet_instances = []
  • facet_classes = list(
  • itertools.chain.from_iterable(pm.hook.register_facet_classes()) )
  • for facet_class in facet_classes:
  • facet_instances.append(
  • facet_class(
  • self.ds,
  • request,
  • database_name,
  • sql=sql_no_order_no_limit,
  • params=params,
  • table=table_name,
  • metadata=table_metadata,
  • row_count=extra_count,
  • )
  • )
  • return facet_instances +
  • async def extra_facet_results(facet_instances):
  • facet_results = {}
  • facets_timed_out = []

  • async def execute_facets(): if not nofacet: # Run them in parallel facet_awaitables = [facet.facet_results() for facet in facet_instances] @@ -607,9 +611,13 @@ class TableView(DataView): facet_results[key] = facet_info facets_timed_out.extend(instance_facets_timed_out)

  • suggested_facets = []

  • return {
  • "results": facet_results,
  • "timed_out": facets_timed_out,
  • }

  • async def execute_suggested_facets():

  • async def extra_suggested_facets(facet_instances):
  • suggested_facets = [] # Calculate suggested facets if ( self.ds.setting("suggest_facets") @@ -624,8 +632,15 @@ class TableView(DataView): ] for suggest_result in await gather(*facet_suggest_awaitables): suggested_facets.extend(suggest_result)
  • return suggested_facets +
  • Faceting

  • if not self.ds.setting("allow_facet") and any(
  • arg.startswith("_facet") for arg in request.args
  • ):
  • raise BadRequest("_facet= is not allowed")

  • await gather(execute_facets(), execute_suggested_facets())

  • pylint: disable=no-member

     # Figure out columns and rows for the query
     columns = [r[0] for r in results.description]
    

    @@ -732,17 +747,56 @@ class TableView(DataView): rows = rows[:page_size]

     # human_description_en combines filters AND search, if provided
    
    • human_description_en = filters.human_description_en(
    • extra=extra_human_descriptions
    • )
    • async def extra_human_description_en():
    • human_description_en = filters.human_description_en(
    • extra=extra_human_descriptions
    • )
    • if sort or sort_desc:
    • human_description_en = " ".join(
    • [b for b in [human_description_en, sorted_by] if b]
    • )
    • return human_description_en

      if sort or sort_desc: sorted_by = "sorted by {}{}".format( (sort or sort_desc), " descending" if sort_desc else "" ) - human_description_en = " ".join( - [b for b in [human_description_en, sorted_by] if b] - ) + + async def extra_next_url(): + return next_url + + async def extra_columns(): + return columns + + async def extra_primary_keys(): + return pks + + registry = Registry( + extra_count, + extra_facet_results, + extra_suggested_facets, + facet_instances, + extra_human_description_en, + extra_next_url, + extra_columns, + extra_primary_keys, + ) + + results = await registry.resolve_multi( + ["extra_{}".format(extra) for extra in extras] + ) + data = { + "ok": True, + "rows": rows[:page_size], + "next": next_value and str(next_value) or None, + } + data.update({ + key.replace("extra_", ""): value + for key, value in results.items() + if key.startswith("extra_") + and key.replace("extra_", "") in extras + }) + return Response.json(data, default=repr)

      async def extra_template(): nonlocal sort @@ -1334,3 +1388,11 @@ class TableDropView(BaseView):

      await db.execute_write_fn(drop_table) return Response.json({"ok": True}, status=200) + + +def _get_extras(request): + extra_bits = request.args.getlist("_extra") + extras = set() + for bit in extra_bits: + extras.update(bit.split(",")) + return extras With that in place, `http://127.0.0.1:8001/content/releases?author=25778&_size=1&_extra=count,primary_keys,columns&_facet=author` returns:json { "ok": true, "rows": [ { "html_url": "https://github.com/eyeseast/geocode-sqlite/releases/tag/0.1.2", "id": 30926270, "author": { "value": 25778, "label": "eyeseast" }, "node_id": "MDc6UmVsZWFzZTMwOTI2Mjcw", "tag_name": "0.1.2", "target_commitish": "master", "name": "v0.1.2", "draft": 0, "prerelease": 1, "created_at": "2020-09-08T17:48:24Z", "published_at": "2020-09-08T17:50:15Z", "body": "Basic API is in place, with CLI support for Google, Bing, MapQuest and Nominatum (OSM) geocoders.", "repo": { "value": 293361514, "label": "geocode-sqlite" }, "reactions": null, "mentions_count": null } ], "next": "30926270", "primary_keys": [ "id" ], "columns": [ "html_url", "id", "author", "node_id", "tag_name", "target_commitish", "name", "draft", "prerelease", "created_at", "published_at", "body", "repo", "reactions", "mentions_count" ], "count": 25, "facet_results": { "results": { "author": { "name": "author", "type": "column", "hideable": true, "toggle_url": "/content/releases?author=25778&_size=1&_extra=count%2Cprimary_keys%2Ccolumns", "results": [ { "value": 25778, "label": "eyeseast", "count": 25, "toggle_url": "http://127.0.0.1:8001/content/releases?_size=1&_extra=count%2Cprimary_keys%2Ccolumns&_facet=author", "selected": true } ], "truncated": false } }, "timed_out": [] } } ```

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
323658641  
Powered by Datasette · Queries took 1.647ms · About: github-to-sqlite