Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions docs/cli-reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -711,14 +711,18 @@ See :ref:`cli_tables`.

::

Usage: sqlite-utils tables [OPTIONS] PATH
Usage: sqlite-utils tables [OPTIONS] PATH [NAMES]...

List the tables in the database

Example:

sqlite-utils tables trees.db

Pass one or more table names to restrict the output to just those tables:

sqlite-utils tables trees.db plants seeds

Options:
--fts4 Just show FTS4 enabled tables
--fts5 Just show FTS5 enabled tables
Expand Down Expand Up @@ -756,14 +760,18 @@ See :ref:`cli_views`.

::

Usage: sqlite-utils views [OPTIONS] PATH
Usage: sqlite-utils views [OPTIONS] PATH [NAMES]...

List the views in the database

Example:

sqlite-utils views trees.db

Pass one or more view names to restrict the output to just those views:

sqlite-utils views trees.db recent_plants

Options:
--counts Include row counts per view
--nl Output newline-delimited JSON
Expand Down
15 changes: 15 additions & 0 deletions docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,19 @@ You can list the names of tables in a database using the ``tables`` command:
{"table": "cats"},
{"table": "chickens"}]

Pass one or more table names to restrict the output to just those tables. This is useful with ``--counts`` against a database that has a large table you want to skip:

.. code-block:: bash

sqlite-utils tables mydb.db dogs cats --counts

.. code-block:: output

[{"table": "dogs", "count": 12},
{"table": "cats", "count": 332}]

The tables are listed in the order you name them. An error is raised, and a non-zero exit code returned, if any of the named tables do not exist.

You can output this list in CSV using the ``--csv`` or ``--tsv`` options:

.. code-block:: bash
Expand Down Expand Up @@ -843,6 +856,8 @@ It takes the same options as the ``tables`` command:
* ``--tsv``
* ``--table``

As with ``tables``, you can pass one or more view names to restrict the output to just those views.

.. note::
In Python: :ref:`db.views or db.view_names() <python_api_views>` CLI reference: :ref:`sqlite-utils views <cli_ref_views>`

Expand Down
34 changes: 33 additions & 1 deletion sqlite_utils/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ def cli():
type=click.Path(exists=True, file_okay=True, dir_okay=False, allow_dash=False),
required=True,
)
@click.argument("names", nargs=-1)
@click.option(
"--fts4", help="Just show FTS4 enabled tables", default=False, is_flag=True
)
Expand All @@ -212,6 +213,7 @@ def cli():
@load_extension_option
def tables(
path,
names,
fts4,
fts5,
counts,
Expand All @@ -235,6 +237,11 @@ def tables(

\b
sqlite-utils tables trees.db

Pass one or more table names to restrict the output to just those tables:

\b
sqlite-utils tables trees.db plants seeds
"""
db = sqlite_utils.Database(path)
_register_db_for_cleanup(db)
Expand All @@ -249,8 +256,25 @@ def tables(

method = db.view if views else db.table

if names:
existing = set(db.view_names() if views else db.table_names())
missing = [name for name in names if name not in existing]
if missing:
label = "view" if views else "table"
if len(missing) == 1:
message = "The following {} does not exist: {}".format(
label, missing[0]
)
else:
message = "The following {}s do not exist: {}".format(
label, ", ".join(missing)
)
raise click.ClickException(message)

def _iter():
if views:
if names:
items = list(names)
elif views:
items = db.view_names()
else:
items = db.table_names(fts4=fts4, fts5=fts5)
Expand Down Expand Up @@ -293,6 +317,7 @@ def _iter():
type=click.Path(exists=True, file_okay=True, dir_okay=False, allow_dash=False),
required=True,
)
@click.argument("names", nargs=-1)
@click.option(
"--counts", help="Include row counts per view", default=False, is_flag=True
)
Expand All @@ -312,6 +337,7 @@ def _iter():
@load_extension_option
def views(
path,
names,
counts,
nl,
arrays,
Expand All @@ -332,10 +358,16 @@ def views(

\b
sqlite-utils views trees.db

Pass one or more view names to restrict the output to just those views:

\b
sqlite-utils views trees.db recent_plants
"""
assert tables.callback is not None
tables.callback(
path=path,
names=names,
fts4=False,
fts5=False,
counts=counts,
Expand Down
51 changes: 51 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,57 @@ def test_tables_schema(db_path):
) == result.output.strip()


def test_tables_specific_names(db_path):
result = CliRunner().invoke(
cli.cli, ["tables", db_path, "Gosh2"], catch_exceptions=False
)
assert '[{"table": "Gosh2"}]' == result.output.strip()


def test_tables_specific_names_preserve_argument_order(db_path):
result = CliRunner().invoke(
cli.cli, ["tables", db_path, "Gosh2", "Gosh"], catch_exceptions=False
)
assert '[{"table": "Gosh2"},\n {"table": "Gosh"}]' == result.output.strip()


def test_tables_specific_names_with_counts(db_path):
result = CliRunner().invoke(
cli.cli, ["tables", db_path, "Gosh", "--counts"], catch_exceptions=False
)
assert '[{"table": "Gosh", "count": 0}]' == result.output.strip()


def test_tables_missing_name_errors(db_path):
result = CliRunner().invoke(cli.cli, ["tables", db_path, "Gosh", "nope"])
assert result.exit_code == 1
assert "The following table does not exist: nope" in result.output


def test_tables_multiple_missing_names_errors(db_path):
result = CliRunner().invoke(cli.cli, ["tables", db_path, "nope", "nope2"])
assert result.exit_code == 1
assert "The following tables do not exist: nope, nope2" in result.output


def test_views_specific_names(db_path):
db = Database(db_path)
db.create_view("v1", "select 1")
db.create_view("v2", "select 2")
result = CliRunner().invoke(
cli.cli, ["views", db_path, "v2"], catch_exceptions=False
)
assert '[{"view": "v2"}]' == result.output.strip()


def test_views_missing_name_errors(db_path):
db = Database(db_path)
db.create_view("v1", "select 1")
result = CliRunner().invoke(cli.cli, ["views", db_path, "nope"])
assert result.exit_code == 1
assert "The following view does not exist: nope" in result.output


@pytest.mark.parametrize(
"options,expected",
[
Expand Down
Loading