kopia lustrzana https://github.com/simonw/datasette
"datasette inspect foo.db" now just calculates table counts
Refs #462 * inspect command now just outputs table counts * test_inspect.py is now only tests for that CLI command * Updated some relevant documentation * Removed docs for /-/inspect since that is about to changedebug-travis
rodzic
ce09e5d2d3
commit
c0d1b4c322
|
@ -1,3 +1,4 @@
|
|||
import asyncio
|
||||
import click
|
||||
from click import formatting
|
||||
from click_default_group import DefaultGroup
|
||||
|
@ -60,7 +61,7 @@ def cli():
|
|||
|
||||
@cli.command()
|
||||
@click.argument("files", type=click.Path(exists=True), nargs=-1)
|
||||
@click.option("--inspect-file", default="inspect-data.json")
|
||||
@click.option("--inspect-file", default="-")
|
||||
@click.option(
|
||||
"sqlite_extensions",
|
||||
"--load-extension",
|
||||
|
@ -70,8 +71,31 @@ def cli():
|
|||
help="Path to a SQLite extension to load",
|
||||
)
|
||||
def inspect(files, inspect_file, sqlite_extensions):
|
||||
app = Datasette(files, sqlite_extensions=sqlite_extensions)
|
||||
open(inspect_file, "w").write(json.dumps(app.inspect(), indent=2))
|
||||
app = Datasette([], immutables=files, sqlite_extensions=sqlite_extensions)
|
||||
if inspect_file == "-":
|
||||
out = sys.stdout
|
||||
else:
|
||||
out = open(inspect_file, "w")
|
||||
loop = asyncio.get_event_loop()
|
||||
inspect_data = loop.run_until_complete(inspect_(files, sqlite_extensions))
|
||||
out.write(json.dumps(inspect_data, indent=2))
|
||||
|
||||
|
||||
async def inspect_(files, sqlite_extensions):
|
||||
app = Datasette([], immutables=files, sqlite_extensions=sqlite_extensions)
|
||||
data = {}
|
||||
for name, database in app.databases.items():
|
||||
counts = await database.table_counts(limit=3600 * 1000)
|
||||
data[name] = {
|
||||
"hash": database.hash,
|
||||
"size": database.size,
|
||||
"file": database.path,
|
||||
"tables": {
|
||||
table_name: {"count": table_count}
|
||||
for table_name, table_count in counts.items()
|
||||
},
|
||||
}
|
||||
return data
|
||||
|
||||
|
||||
@cli.group()
|
||||
|
|
|
@ -7,7 +7,7 @@ SQLite includes `a powerful mechanism for enabling full-text search <https://www
|
|||
|
||||
.. image:: full_text_search.png
|
||||
|
||||
Datasette detects which tables have been configured for full-text search when it first inspects the database on startup (or via the ``datasette inspect`` command). You can visit the ``/-/inspect`` page on your Datasette instance to see the results of this inspection. Tables that have been configured for full-text search will have their ``fts_table`` property set to the name of another table (tables without full-text search will have this property set to ``null``).
|
||||
Datasette automatically detects which tables have been configured for full-text search.
|
||||
|
||||
FTS versions
|
||||
------------
|
||||
|
@ -71,6 +71,8 @@ And then populate it like this:
|
|||
|
||||
You can use this technique to populate the full-text search index from any combination of tables and joins that makes sense for your project.
|
||||
|
||||
The `sqlite-utils tool <https://sqlite-utils.readthedocs.io/en/latest/cli.html#configuring-full-text-search>`__ provides a command-line mechanism that can be used to implement the above steps.
|
||||
|
||||
.. _full_text_search_table_or_view:
|
||||
|
||||
Configuring full-text search for a table or view
|
||||
|
|
|
@ -21,40 +21,6 @@ Shows the contents of the ``metadata.json`` file that was passed to ``datasette
|
|||
"databases": {...}
|
||||
}
|
||||
|
||||
.. _JsonDataView_inspect:
|
||||
|
||||
/-/inspect
|
||||
----------
|
||||
|
||||
Shows the result of running ``datasette inspect`` on the currently loaded databases. This is run automatically when Datasette starts up, or can be run as a separate step and passed to ``datasette serve --inspect-file``.
|
||||
|
||||
This is an internal implementation detail of Datasette and the format should not be considered stable - it is likely to change in undocumented ways between different releases.
|
||||
|
||||
`Inspect example <https://fivethirtyeight.datasettes.com/-/inspect>`_::
|
||||
|
||||
{
|
||||
"fivethirtyeight": {
|
||||
"file": "fivethirtyeight.db",
|
||||
"hash": "5de27e3eceb3f5ba817e0b2e066cea77832592b62d94690b5102a48f385b95fb",
|
||||
"tables": {
|
||||
"./index": {
|
||||
"columns": [
|
||||
"dataset_url",
|
||||
"article_url",
|
||||
"live"
|
||||
],
|
||||
"count": 125,
|
||||
"foreign_keys": {
|
||||
"incoming": [],
|
||||
"outgoing": []
|
||||
},
|
||||
"fts_table": null,
|
||||
"hidden": false,
|
||||
"name": "./index",
|
||||
"primary_keys": []
|
||||
},
|
||||
...
|
||||
|
||||
.. _JsonDataView_versions:
|
||||
|
||||
/-/versions
|
||||
|
|
|
@ -1,92 +1,28 @@
|
|||
from datasette.app import Datasette
|
||||
from datasette.utils import sqlite3
|
||||
import os
|
||||
import pytest
|
||||
import tempfile
|
||||
from .fixtures import app_client
|
||||
from datasette.cli import cli
|
||||
from click.testing import CliRunner
|
||||
import json
|
||||
|
||||
|
||||
TABLES = """
|
||||
CREATE TABLE "election_results" (
|
||||
"county" INTEGER,
|
||||
"party" INTEGER,
|
||||
"office" INTEGER,
|
||||
"votes" INTEGER,
|
||||
FOREIGN KEY (county) REFERENCES county(id),
|
||||
FOREIGN KEY (party) REFERENCES party(id),
|
||||
FOREIGN KEY (office) REFERENCES office(id)
|
||||
);
|
||||
|
||||
CREATE VIRTUAL TABLE "election_results_fts" USING FTS4 ("county", "party");
|
||||
|
||||
CREATE TABLE "county" (
|
||||
"id" INTEGER PRIMARY KEY ,
|
||||
"name" TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE "party" (
|
||||
"id" INTEGER PRIMARY KEY ,
|
||||
"name" TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE "office" (
|
||||
"id" INTEGER PRIMARY KEY ,
|
||||
"name" TEXT
|
||||
);
|
||||
"""
|
||||
def test_inspect_cli(app_client):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["inspect", "fixtures.db"])
|
||||
data = json.loads(result.output)
|
||||
assert ["fixtures"] == list(data.keys())
|
||||
database = data["fixtures"]
|
||||
assert "fixtures.db" == database["file"]
|
||||
assert isinstance(database["hash"], str)
|
||||
assert 64 == len(database["hash"])
|
||||
for table_name, expected_count in {
|
||||
"Table With Space In Name": 0,
|
||||
"facetable": 15
|
||||
}.items():
|
||||
assert expected_count == database["tables"][table_name]["count"]
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def ds_instance():
|
||||
with tempfile.TemporaryDirectory() as tmpdir:
|
||||
filepath = os.path.join(tmpdir, "fixtures.db")
|
||||
conn = sqlite3.connect(filepath)
|
||||
conn.executescript(TABLES)
|
||||
yield Datasette([filepath])
|
||||
|
||||
|
||||
def test_inspect_hidden_tables(ds_instance):
|
||||
info = ds_instance.inspect()
|
||||
tables = info["fixtures"]["tables"]
|
||||
expected_hidden = (
|
||||
"election_results_fts",
|
||||
"election_results_fts_content",
|
||||
"election_results_fts_docsize",
|
||||
"election_results_fts_segdir",
|
||||
"election_results_fts_segments",
|
||||
"election_results_fts_stat",
|
||||
)
|
||||
expected_visible = ("election_results", "county", "party", "office")
|
||||
assert sorted(expected_hidden) == sorted(
|
||||
[table for table in tables if tables[table]["hidden"]]
|
||||
)
|
||||
assert sorted(expected_visible) == sorted(
|
||||
[table for table in tables if not tables[table]["hidden"]]
|
||||
)
|
||||
|
||||
|
||||
def test_inspect_foreign_keys(ds_instance):
|
||||
info = ds_instance.inspect()
|
||||
tables = info["fixtures"]["tables"]
|
||||
for table_name in ("county", "party", "office"):
|
||||
assert 0 == tables[table_name]["count"]
|
||||
foreign_keys = tables[table_name]["foreign_keys"]
|
||||
assert [] == foreign_keys["outgoing"]
|
||||
assert [
|
||||
{
|
||||
"column": "id",
|
||||
"other_column": table_name,
|
||||
"other_table": "election_results",
|
||||
}
|
||||
] == foreign_keys["incoming"]
|
||||
|
||||
election_results = tables["election_results"]
|
||||
assert 0 == election_results["count"]
|
||||
assert sorted(
|
||||
[
|
||||
{"column": "county", "other_column": "id", "other_table": "county"},
|
||||
{"column": "party", "other_column": "id", "other_table": "party"},
|
||||
{"column": "office", "other_column": "id", "other_table": "office"},
|
||||
],
|
||||
key=lambda d: d["column"],
|
||||
) == sorted(election_results["foreign_keys"]["outgoing"], key=lambda d: d["column"])
|
||||
assert [] == election_results["foreign_keys"]["incoming"]
|
||||
def test_inspect_cli_writes_to_file(app_client):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["inspect", "fixtures.db", "--inspect-file", "foo.json"])
|
||||
assert 0 == result.exit_code, result.output
|
||||
data = json.load(open("foo.json"))
|
||||
assert ["fixtures"] == list(data.keys())
|
||||
|
|
Ładowanie…
Reference in New Issue