From b73e0e1021662866c179c3d82bc003449ef46c02 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sat, 11 Jul 2026 16:35:27 -0700 Subject: [PATCH] TransformError() on strict=True if SQLite does not suppor strict Refs https://github.com/simonw/sqlite-utils/pull/788#issuecomment-4948479356 --- docs/changelog.rst | 2 +- docs/cli.rst | 2 +- docs/python-api.rst | 2 ++ sqlite_utils/db.py | 2 ++ tests/test_transform.py | 12 ++++++++++++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index 8d05b40..a8a2a26 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,7 +9,7 @@ Unreleased ---------- -- ``table.transform()`` now accepts ``strict=True`` or ``strict=False`` to change a table's SQLite strict mode. Omitting the option, or passing ``strict=None``, preserves the existing mode. (:issue:`787`) +- ``table.transform()`` now accepts ``strict=True`` or ``strict=False`` to change a table's SQLite strict mode. Omitting the option, or passing ``strict=None``, preserves the existing mode. Requesting strict mode raises ``TransformError`` if the available SQLite version does not support strict tables. (:issue:`787`) - The ``sqlite-utils transform`` command now accepts ``--strict`` and ``--no-strict`` to change a table's SQLite strict mode. Omitting both options preserves the existing mode. (:issue:`787`) - ``sqlite-utils query`` can now read the SQL query from standard input by passing ``-`` in place of the query, for example ``echo "select * from dogs" | sqlite-utils query dogs.db -``. (:issue:`765`) - ``sqlite-utils insert`` and ``sqlite-utils upsert`` now accept a ``--code`` option for :ref:`providing a block of Python code ` (or a path to a ``.py`` file) that defines a ``rows()`` function or ``rows`` iterable of rows to insert, as an alternative to importing from a file. (:issue:`684`) diff --git a/docs/cli.rst b/docs/cli.rst index a8ab53c..dce36d9 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -2229,7 +2229,7 @@ Every option for this table (with the exception of ``--pk-none``) can be specifi Add a foreign key constraint to ``column`` pointing to ``other_table.other_column``. ``--strict`` - Convert the table to a `SQLite STRICT table `__. If existing rows contain values that are incompatible with their declared column types the transformation fails and the original table is left unchanged. + Convert the table to a `SQLite STRICT table `__. The command fails if the available SQLite version does not support strict tables. If existing rows contain values that are incompatible with their declared column types the transformation fails and the original table is left unchanged. ``--no-strict`` Convert a strict table back to a regular non-strict table. diff --git a/docs/python-api.rst b/docs/python-api.rst index e6b2443..8b07677 100644 --- a/docs/python-api.rst +++ b/docs/python-api.rst @@ -1772,6 +1772,8 @@ Pass ``strict=False`` to convert a strict table back to a regular non-strict tab The default is ``strict=None``, which preserves the table's existing strict mode. +Passing ``strict=True`` raises ``sqlite_utils.db.TransformError`` if the available SQLite version does not support strict tables. + Converting to a strict table validates all existing rows as they are copied into the replacement table. If a value is incompatible with its declared column type, SQLite raises ``sqlite3.IntegrityError`` and the transformation is rolled back, leaving the original table and its data unchanged. .. _python_api_transform_rename_columns: diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index 879c49d..d709fb9 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -2634,6 +2634,8 @@ class Table(Queryable): :param strict: Set to ``True`` to make the table strict or ``False`` to make it non-strict. Defaults to ``None``, which preserves the existing strict mode. """ + if strict is True and not self.db.supports_strict: + raise TransformError("SQLite does not support STRICT tables") types = types or {} rename = rename or {} drop = drop or set() diff --git a/tests/test_transform.py b/tests/test_transform.py index 14f403a..f0f5019 100644 --- a/tests/test_transform.py +++ b/tests/test_transform.py @@ -615,6 +615,18 @@ def test_transform_strict_updates_default(fresh_db): assert table.strict is False +@pytest.mark.parametrize("method_name", ("transform", "transform_sql")) +def test_transform_to_strict_not_supported(fresh_db, method_name): + table = fresh_db["items"] + table.create({"id": int}) + fresh_db._supports_strict = False + + with pytest.raises(TransformError, match="SQLite does not support STRICT tables"): + getattr(table, method_name)(strict=True) + + assert table.strict is False + + @pytest.mark.parametrize( "indexes, transform_params", [