From c236894caa976d4ea5c7503e9331a3e9d2fbb1c4 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Thu, 25 Feb 2021 09:05:08 -0800 Subject: [PATCH] table.drop(ignore=True) option, refs #237 --- docs/python-api.rst | 6 ++++++ sqlite_utils/db.py | 16 ++++++++++++---- tests/test_create.py | 16 ++++++++++++++++ tests/test_extract.py | 4 +++- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/docs/python-api.rst b/docs/python-api.rst index c0eb59339..e5ffd44df 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -1026,6 +1026,12 @@ You can drop a table or view using the ``.drop()`` method: db["my_table"].drop() +Pass ``ignore=True`` if you want to ignore the error caused by the table or view not existing. + +.. code-block:: python + + db["my_table"].drop(ignore=True) + .. _python_api_transform: Transforming a table diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 246064cc2..d9a6b26b1 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -1212,8 +1212,12 @@ def add_column( self.add_foreign_key(col_name, fk, fk_col) return self - def drop(self): - self.db.execute("DROP TABLE [{}]".format(self.name)) + def drop(self, ignore=False): + try: + self.db.execute("DROP TABLE [{}]".format(self.name)) + except sqlite3.OperationalError: + if not ignore: + raise def guess_foreign_table(self, column): column = column.lower() @@ -2195,8 +2199,12 @@ def __repr__(self): self.name, ", ".join(c.name for c in self.columns) ) - def drop(self): - self.db.execute("DROP VIEW [{}]".format(self.name)) + def drop(self, ignore=False): + try: + self.db.execute("DROP VIEW [{}]".format(self.name)) + except sqlite3.OperationalError: + if not ignore: + raise def enable_fts(self, *args, **kwargs): raise NotImplementedError( diff --git a/tests/test_create.py b/tests/test_create.py index 09a695e1b..c1daf6b26 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -6,6 +6,7 @@ NoObviousTable, ForeignKey, Table, + View, ) from sqlite_utils.utils import sqlite3 import collections @@ -944,6 +945,21 @@ def test_drop_view(fresh_db): assert [] == fresh_db.view_names() +def test_drop_ignore(fresh_db): + with pytest.raises(sqlite3.OperationalError): + fresh_db["does_not_exist"].drop() + fresh_db["does_not_exist"].drop(ignore=True) + # Testing view is harder, we need to create it in order + # to get a View object, then drop it twice + fresh_db.create_view("foo_view", "select 1") + view = fresh_db["foo_view"] + assert isinstance(view, View) + view.drop() + with pytest.raises(sqlite3.OperationalError): + view.drop() + view.drop(ignore=True) + + def test_insert_all_empty_list(fresh_db): fresh_db["t"].insert({"foo": 1}) assert 1 == fresh_db["t"].count diff --git a/tests/test_extract.py b/tests/test_extract.py index 7a663b509..9eae70496 100644 --- a/tests/test_extract.py +++ b/tests/test_extract.py @@ -28,7 +28,9 @@ def test_extract_single_column(fresh_db, table, fk_column): " [name] TEXT,\n" " [{}] INTEGER,\n".format(expected_fk) + " [end] INTEGER,\n" - + " FOREIGN KEY([{}]) REFERENCES [{}]([id])\n".format(expected_fk, expected_table) + + " FOREIGN KEY([{}]) REFERENCES [{}]([id])\n".format( + expected_fk, expected_table + ) + ")" ) assert fresh_db[expected_table].schema == (