From 033cf0bcbbcadd0256d0c43fb7b9d3053727b4fe Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Wed, 1 May 2019 18:12:58 -0700 Subject: [PATCH] DatabaseView no longer uses .inspect(), closes #420 --- datasette/app.py | 11 ++++-- datasette/views/database.py | 71 +++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/datasette/app.py b/datasette/app.py index 12abaab9..282c161a 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -130,12 +130,19 @@ class ConnectedDatabase: self.is_mutable = is_mutable self.is_memory = is_memory self.hash = None - self.size = None + self.cached_size = None self.cached_table_counts = None if not self.is_mutable: p = Path(path) self.hash = inspect_hash(p) - self.size = p.stat().st_size + self.cached_size = p.stat().st_size + + @property + def size(self): + if self.cached_size is not None: + return self.cached_size + else: + return Path(self.path).stat().st_size async def table_counts(self, limit=10): if not self.is_mutable and self.cached_table_counts is not None: diff --git a/datasette/views/database.py b/datasette/views/database.py index d1185eef..5fab04b0 100644 --- a/datasette/views/database.py +++ b/datasette/views/database.py @@ -2,13 +2,19 @@ import os from sanic import response -from datasette.utils import to_css_class, validate_sql_select +from datasette.utils import ( + detect_fts, + detect_primary_keys, + get_all_foreign_keys, + to_css_class, + validate_sql_select, +) from .base import BaseView, DatasetteError class DatabaseView(BaseView): - name = 'database' + name = "database" async def data(self, request, database, hash, default_labels=False, _size=None): if request.args.get("sql"): @@ -18,29 +24,58 @@ class DatabaseView(BaseView): validate_sql_select(sql) return await self.custom_sql(request, database, hash, sql, _size=_size) - info = self.ds.inspect()[database] + db = self.ds.databases[database] + + table_counts = await db.table_counts(5) + views = await db.view_names() + hidden_table_names = set(await db.hidden_table_names()) + all_foreign_keys = await self.ds.execute_against_connection_in_thread( + database, get_all_foreign_keys + ) + metadata = (self.ds.metadata("databases") or {}).get(database, {}) self.ds.update_with_inherited_metadata(metadata) - tables = list(info["tables"].values()) + + tables = [] + for table in table_counts: + table_columns = await self.ds.table_columns(database, table) + tables.append( + { + "name": table, + "columns": table_columns, + "primary_keys": await self.ds.execute_against_connection_in_thread( + database, lambda conn: detect_primary_keys(conn, table) + ), + "count": table_counts[table], + "hidden": table in hidden_table_names, + "fts_table": await self.ds.execute_against_connection_in_thread( + database, lambda conn: detect_fts(conn, table) + ), + "foreign_keys": all_foreign_keys[table], + } + ) + tables.sort(key=lambda t: (t["hidden"], t["name"])) - return { - "database": database, - "size": info["size"], - "tables": tables, - "hidden_count": len([t for t in tables if t["hidden"]]), - "views": info["views"], - "queries": self.ds.get_canned_queries(database), - }, { - "show_hidden": request.args.get("_show_hidden"), - "editable": True, - "metadata": metadata, - }, ( - "database-{}.html".format(to_css_class(database)), "database.html" + return ( + { + "database": database, + "size": db.size, + "tables": tables, + "hidden_count": len([t for t in tables if t["hidden"]]), + "views": views, + "queries": self.ds.get_canned_queries(database), + }, + { + "show_hidden": request.args.get("_show_hidden"), + "editable": True, + "metadata": metadata, + }, + ("database-{}.html".format(to_css_class(database)), "database.html"), ) class DatabaseDownload(BaseView): - name = 'database_download' + name = "database_download" async def view_get(self, request, database, hash, correct_hash_present, **kwargs): if not self.ds.config("allow_download"):