From 82e8cd36673fb154b484d3a426feff0a219e3eb1 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sat, 22 Jul 2023 12:38:31 -0700 Subject: [PATCH] db.rename_table() method, refs #565 --- docs/python-api.rst | 22 ++++++++++++++++++++-- sqlite_utils/db.py | 13 +++++++++++++ tests/test_create.py | 11 +++++++++++ 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/docs/python-api.rst b/docs/python-api.rst index 33a50ba4..bd2f5b99 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -638,7 +638,7 @@ You can leave off the third item in the tuple to have the referenced column auto .. _python_api_table_configuration: Table configuration options -=========================== +--------------------------- The ``.insert()``, ``.upsert()``, ``.insert_all()`` and ``.upsert_all()`` methods each take a number of keyword arguments, some of which influence what happens should they cause a table to be created and some of which affect the behavior of those methods. @@ -660,7 +660,7 @@ The configuration options that can be specified in this way are ``pk``, ``foreig .. _python_api_defaults_not_null: Setting defaults and not null constraints -========================================= +----------------------------------------- Each of the methods that can cause a table to be created take optional arguments ``not_null=set()`` and ``defaults=dict()``. The methods that take these optional arguments are: @@ -699,6 +699,24 @@ Here's an example that uses these features: # [score] INTEGER NOT NULL DEFAULT 1 # ) + +.. _python_api_rename_table: + +Renaming a table +================ + +The ``db.rename_table(old_name, new_name)`` method can be used to rename a table: + +.. code-block:: python + + db.rename_table("my_table", "new_name_for_my_table") + +This executes the following SQL: + +.. code-block:: sql + + ALTER TABLE [my_table] RENAME TO [new_name_for_my_table] + .. _python_api_duplicate: Duplicating tables diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 36ec5241..7098ec0f 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -1040,6 +1040,19 @@ def create_table( ) return cast(Table, created_table) + def rename_table(self, name: str, new_name: str): + """ + Rename a table. + + :param name: Current table name + :param new_name: Name to rename it to + """ + self.execute( + "ALTER TABLE [{name}] RENAME TO [{new_name}]".format( + name=name, new_name=new_name + ) + ) + def create_view( self, name: str, sql: str, ignore: bool = False, replace: bool = False ): diff --git a/tests/test_create.py b/tests/test_create.py index 7a25bca6..63f09913 100644 --- a/tests/test_create.py +++ b/tests/test_create.py @@ -1279,3 +1279,14 @@ def test_create_transform(fresh_db, cols, kwargs, expected_schema, should_transf new_schema = fresh_db["demo"].schema assert new_schema == expected_schema, repr(new_schema) assert fresh_db["demo"].count == 1 + + +def test_rename_table(fresh_db): + fresh_db["t"].insert({"foo": "bar"}) + assert ["t"] == fresh_db.table_names() + fresh_db.rename_table("t", "renamed") + assert ["renamed"] == fresh_db.table_names() + assert [{"foo": "bar"}] == list(fresh_db["renamed"].rows) + # Should error if table does not exist: + with pytest.raises(sqlite3.OperationalError): + fresh_db.rename_table("does_not_exist", "renamed")