Added sqlite-utils create-view command, closes #107

This commit is contained in:
Simon Willison 2020-05-03 08:36:29 -07:00
commit d16097231c
3 changed files with 113 additions and 0 deletions

View file

@ -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

View file

@ -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",

View file

@ -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