diff --git a/datasette/app.py b/datasette/app.py index a4b8f7f0..d092e1ad 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -605,7 +605,7 @@ class Datasette: truncated = False except sqlite3.OperationalError as e: if e.args == ('interrupted',): - raise InterruptedError(e) + raise InterruptedError(e, sql, params) if log_sql_errors: print( "ERROR: conn={}, sql = {}, params = {}: {}".format( diff --git a/datasette/facets.py b/datasette/facets.py index cb2e9f9a..a8ff0c40 100644 --- a/datasette/facets.py +++ b/datasette/facets.py @@ -8,6 +8,7 @@ from datasette.utils import ( path_with_added_args, path_with_removed_args, detect_json1, + InterruptedError, InvalidSql, sqlite3, ) @@ -142,7 +143,7 @@ class ColumnFacet(Facet): ), }) except InterruptedError: - pass + continue return suggested_facets async def facet_results(self, sql, params): @@ -238,6 +239,9 @@ class ManyToManyFacet(Facet): all_foreign_keys = await self.ds.execute_against_connection_in_thread( self.database, get_all_foreign_keys ) + if not all_foreign_keys.get(self.table): + # It's probably a view + return [] incoming = all_foreign_keys[self.table]["incoming"] # Do any of these incoming tables have exactly two outgoing keys? for fk in incoming: @@ -377,7 +381,7 @@ class DateFacet(Facet): suggested_facet_sql = """ select date({column}) from ( {sql} - ) limit 100; + ) where {column} glob "????-??-??" limit 100; """.format( column=escape_sqlite(column), sql=sql, @@ -429,7 +433,7 @@ class DateFacet(Facet): {sql} ) where date({col}) is not null - group by date({col}) order by date({col}) desc limit {limit} + group by date({col}) order by count desc limit {limit} """.format( col=escape_sqlite(column), sql=sql, @@ -577,7 +581,6 @@ class EmojiFacet(Facet): ), }) except (InterruptedError, sqlite3.OperationalError) as e: - print(" oh no ", e) continue return suggested_facets diff --git a/datasette/views/table.py b/datasette/views/table.py index 1a7231fb..30fa476c 100644 --- a/datasette/views/table.py +++ b/datasette/views/table.py @@ -464,11 +464,14 @@ class TableView(RowTableShared): else: page_size = self.ds.page_size - sql = "select {select} from {table_name} {where}{order_by}limit {limit}{offset}".format( + sql_no_limit = "select {select} from {table_name} {where}{order_by}".format( select=select, table_name=escape_sqlite(table), where=where_clause, order_by=order_by, + ) + sql = "{sql_no_limit} limit {limit}{offset}".format( + sql_no_limit=sql_no_limit.rstrip(), limit=page_size + 1, offset=offset, ) @@ -498,7 +501,7 @@ class TableView(RowTableShared): for facet in facet_instances: instance_facet_results, instance_facets_timed_out = await facet.facet_results( - sql, params, + sql_no_limit, params, ) facet_results.update(instance_facet_results) facets_timed_out.extend(instance_facets_timed_out) @@ -605,7 +608,7 @@ class TableView(RowTableShared): for facet in facet_instances: # TODO: ensure facet is not suggested if it is already active # used to use 'if facet_column in facets' for this - suggested_facets.extend(await facet.suggest(sql, params, filtered_table_rows_count)) + suggested_facets.extend(await facet.suggest(sql_no_limit, params, filtered_table_rows_count)) # human_description_en combines filters AND search, if provided human_description_en = filters.human_description_en(extra=search_descriptions) diff --git a/docs/plugins.rst b/docs/plugins.rst index 984e5c95..103e8a2b 100644 --- a/docs/plugins.rst +++ b/docs/plugins.rst @@ -551,3 +551,12 @@ The ``template``, ``database`` and ``table`` options can be used to return diffe The ``datasette`` instance is provided primarily so that you can consult any plugin configuration options that may have been set, using the ``datasette.plugin_config(plugin_name)`` method documented above. The string that you return from this function will be treated as "safe" for inclusion in a ``