diff --git a/docs/python-api.rst b/docs/python-api.rst index f03f963..d575ba6 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -144,6 +144,8 @@ The ``Database`` object also works as a context manager, which will automaticall db["my_table"].insert({"name": "Example"}) # Connection is automatically closed here +Exiting the block closes the connection without committing, so any changes that are still inside an open transaction at that point - for example writes made with raw ``db.execute()`` calls - will be rolled back. Commit explicitly, or use methods such as ``.insert()`` and the ``db.atomic()`` context manager which commit their own transactions. + .. _python_api_attach: Attaching additional databases diff --git a/tests/test_constructor.py b/tests/test_constructor.py index 8743911..0798996 100644 --- a/tests/test_constructor.py +++ b/tests/test_constructor.py @@ -29,6 +29,21 @@ def test_sqlite_version(): assert actual == as_string +def test_database_context_manager(tmpdir): + path = str(tmpdir / "test.db") + with Database(path) as db: + db["t"].insert({"id": 1}) + # A raw write left uncommitted on purpose: + db.execute("insert into t (id) values (2)") + # The connection is closed... + with pytest.raises(sqlite3.ProgrammingError): + db.execute("select 1") + # ... and the uncommitted change was rolled back, not committed + db2 = Database(path) + assert [r["id"] for r in db2["t"].rows] == [1] + db2.close() + + @pytest.mark.parametrize("memory", [True, False]) def test_database_close(tmpdir, memory): if memory: