From d16097231c5e51ea857b58c700f97a17b68dc583 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sun, 3 May 2020 08:36:29 -0700 Subject: [PATCH] Added sqlite-utils create-view command, closes #107 --- docs/cli.rst | 15 +++++++++++ sqlite_utils/cli.py | 32 ++++++++++++++++++++++ tests/test_cli.py | 66 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) diff --git a/docs/cli.rst b/docs/cli.rst index 7c0c9c5..40ac963 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -401,6 +401,21 @@ You can specify foreign key relationships between the tables you are creating us If a table with the same name already exists, you will get an error. You can choose to silently ignore this error with ``--ignore``, or you can replace the existing table with a new, empty table using ``--replace``. + +.. _cli_create_view: + +Creating views +============== + +You can create a view using the ``create-view`` command:: + + $ sqlite-utils create-view mydb.db version "select sqlite_version()" + + $ sqlite-utils mydb.db "select * from version" + [{"sqlite_version()": "3.31.1"}] + +Use ``--replace`` to replace an existing view of the same name, and ``--ignore`` to do nothing if a view already exists. + .. _cli_add_column: Adding columns diff --git a/sqlite_utils/cli.py b/sqlite_utils/cli.py index 8a7fabb..f1b5ac6 100644 --- a/sqlite_utils/cli.py +++ b/sqlite_utils/cli.py @@ -594,6 +594,38 @@ def create_table(path, table, columns, pk, not_null, default, fk, ignore, replac ) +@cli.command(name="create-view") +@click.argument( + "path", + type=click.Path(file_okay=True, dir_okay=False, allow_dash=False), + required=True, +) +@click.argument("view") +@click.argument("select") +@click.option( + "--ignore", is_flag=True, help="If view already exists, do nothing", +) +@click.option( + "--replace", is_flag=True, help="If view already exists, replace it", +) +def create_view(path, view, select, ignore, replace): + "Create a view for the provided SELECT query" + db = sqlite_utils.Database(path) + # Does view already exist? + if view in db.view_names(): + if ignore: + return + elif replace: + db[view].drop() + else: + raise click.ClickException( + 'View "{}" already exists. Use --replace to delete and replace it.'.format( + view + ) + ) + db.create_view(view, select) + + @cli.command() @click.argument( "path", diff --git a/tests/test_cli.py b/tests/test_cli.py index 7d653e1..32ea1db 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -999,3 +999,69 @@ def test_create_table_replace(): ) assert 0 == result.exit_code assert "CREATE TABLE [dogs] (\n [id] INTEGER\n)" == db["dogs"].schema + + +def test_create_view(): + runner = CliRunner() + with runner.isolated_filesystem(): + db = Database("test.db") + result = runner.invoke( + cli.cli, ["create-view", "test.db", "version", "select sqlite_version()"] + ) + assert 0 == result.exit_code + assert "CREATE VIEW version AS select sqlite_version()" == db["version"].schema + + +def test_create_view_error_if_view_exists(): + runner = CliRunner() + with runner.isolated_filesystem(): + db = Database("test.db") + db.create_view("version", "select sqlite_version() + 1") + result = runner.invoke( + cli.cli, ["create-view", "test.db", "version", "select sqlite_version()"] + ) + assert 1 == result.exit_code + assert ( + 'Error: View "version" already exists. Use --replace to delete and replace it.' + == result.output.strip() + ) + + +def test_create_view_ignore(): + runner = CliRunner() + with runner.isolated_filesystem(): + db = Database("test.db") + db.create_view("version", "select sqlite_version() + 1") + result = runner.invoke( + cli.cli, + [ + "create-view", + "test.db", + "version", + "select sqlite_version()", + "--ignore", + ], + ) + assert 0 == result.exit_code + assert ( + "CREATE VIEW version AS select sqlite_version() + 1" == db["version"].schema + ) + + +def test_create_view_replace(): + runner = CliRunner() + with runner.isolated_filesystem(): + db = Database("test.db") + db.create_view("version", "select sqlite_version() + 1") + result = runner.invoke( + cli.cli, + [ + "create-view", + "test.db", + "version", + "select sqlite_version()", + "--replace", + ], + ) + assert 0 == result.exit_code + assert "CREATE VIEW version AS select sqlite_version()" == db["version"].schema