create-table --ignore and --replace, refs #27

This commit is contained in:
Simon Willison 2020-05-03 08:24:39 -07:00
commit 9f6085b4e4
4 changed files with 62 additions and 1 deletions

View file

@ -399,6 +399,8 @@ You can specify foreign key relationships between the tables you are creating us
[author_id] INTEGER REFERENCES [authors]([id])
)
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_add_column:
Adding columns

View file

@ -262,6 +262,8 @@ The first argument here is a dictionary specifying the columns you would like to
This method takes optional arguments ``pk=``, ``column_order=``, ``foreign_keys=``, ``not_null=set()`` and ``defaults=dict()`` - explained below.
You can pass ``ignore=True`` to silently ignore an existing table and do nothing, or ``replace=True`` to replace that table with a new, empty table.
.. _python_api_compound_primary_keys:
Compound primary keys

View file

@ -554,7 +554,13 @@ def upsert(
type=(str, str, str),
help="Column, other table, other column to set as a foreign key",
)
def create_table(path, table, columns, pk, not_null, default, fk):
@click.option(
"--ignore", is_flag=True, help="If table already exists, do nothing",
)
@click.option(
"--replace", is_flag=True, help="If table already exists, replace it",
)
def create_table(path, table, columns, pk, not_null, default, fk, ignore, replace):
"Add an index to the specified table covering the specified columns"
db = sqlite_utils.Database(path)
if len(columns) % 2 == 1:
@ -571,6 +577,18 @@ def create_table(path, table, columns, pk, not_null, default, fk):
"column types must be one of {}".format(VALID_COLUMN_TYPES)
)
coltypes[name] = ctype.upper()
# Does table already exist?
if table in db.table_names():
if ignore:
return
elif replace:
db[table].drop()
else:
raise click.ClickException(
'Table "{}" already exists. Use --replace to delete and replace it.'.format(
table
)
)
db[table].create(
coltypes, pk=pk, not_null=not_null, defaults=dict(default), foreign_keys=fk
)

View file

@ -960,3 +960,42 @@ def test_create_table_foreign_key():
" [author_id] INTEGER REFERENCES [authors]([id])\n"
")"
) == db["books"].schema
def test_create_table_error_if_table_exists():
runner = CliRunner()
with runner.isolated_filesystem():
db = Database("test.db")
db["dogs"].insert({"name": "Cleo"})
result = runner.invoke(
cli.cli, ["create-table", "test.db", "dogs", "id", "integer"]
)
assert 1 == result.exit_code
assert (
'Error: Table "dogs" already exists. Use --replace to delete and replace it.'
== result.output.strip()
)
def test_create_table_ignore():
runner = CliRunner()
with runner.isolated_filesystem():
db = Database("test.db")
db["dogs"].insert({"name": "Cleo"})
result = runner.invoke(
cli.cli, ["create-table", "test.db", "dogs", "id", "integer", "--ignore"]
)
assert 0 == result.exit_code
assert "CREATE TABLE [dogs] (\n [name] TEXT\n)" == db["dogs"].schema
def test_create_table_replace():
runner = CliRunner()
with runner.isolated_filesystem():
db = Database("test.db")
db["dogs"].insert({"name": "Cleo"})
result = runner.invoke(
cli.cli, ["create-table", "test.db", "dogs", "id", "integer", "--replace"]
)
assert 0 == result.exit_code
assert "CREATE TABLE [dogs] (\n [id] INTEGER\n)" == db["dogs"].schema