mirror of
https://github.com/simonw/sqlite-utils.git
synced 2026-09-07 17:14:09 +02:00
Restore previous legacy_alter_table value after transform
transform_sql() now reads the connection's current PRAGMA legacy_alter_table value and emits a closing pragma that restores it, instead of always resetting it to OFF. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
8f264e8d2a
commit
4b66d515a3
3 changed files with 26 additions and 3 deletions
|
|
@ -1995,7 +1995,7 @@ Tables that are referenced by views can be safely transformed - the view definit
|
|||
|
||||
A view that references a column which the transform renamed or dropped will remain defined but will raise a ``no such column`` error when it is next queried. This is inherent to SQLite views, whose SQL is stored as text - if you rename or drop columns that a view depends on you should update that view definition yourself.
|
||||
|
||||
To achieve this, the SQL produced by ``transform_sql()`` brackets its ``ALTER TABLE ... RENAME TO`` statements with ``PRAGMA legacy_alter_table=ON`` and ``PRAGMA legacy_alter_table=OFF`` - without this, SQLite would attempt to rewrite references to the renamed table in every view definition, which fails when a view references the table that was just dropped. One consequence is that ``PRAGMA legacy_alter_table`` is reset to ``OFF`` (the SQLite default) after a transform, even if it was previously set to ``ON`` for the connection.
|
||||
To achieve this, the SQL produced by ``transform_sql()`` turns on ``PRAGMA legacy_alter_table`` for its ``ALTER TABLE ... RENAME TO`` statements, then restores the pragma to the value it had when the SQL was generated - without this, SQLite would attempt to rewrite references to the renamed table in every view definition, which fails when a view references the table that was just dropped.
|
||||
|
||||
.. _python_api_transform_sql:
|
||||
|
||||
|
|
|
|||
|
|
@ -2830,7 +2830,12 @@ class Table(Queryable):
|
|||
# references the table that was just dropped - and with keep_table=
|
||||
# would silently repoint views at the backup table. These renames are
|
||||
# an implementation detail of transform(), so use legacy_alter_table
|
||||
# to leave view definitions untouched.
|
||||
# to leave view definitions untouched, restoring the connection's
|
||||
# current value afterwards.
|
||||
legacy_alter_table_row = self.db.execute("PRAGMA legacy_alter_table").fetchone()
|
||||
legacy_alter_table_was_on = bool(
|
||||
legacy_alter_table_row and legacy_alter_table_row[0]
|
||||
)
|
||||
if keep_table:
|
||||
sqls.append("PRAGMA legacy_alter_table=ON;")
|
||||
sqls.append(
|
||||
|
|
@ -2842,7 +2847,11 @@ class Table(Queryable):
|
|||
sqls.append(
|
||||
f"ALTER TABLE {quote_identifier(new_table_name)} RENAME TO {quote_identifier(self.name)};"
|
||||
)
|
||||
sqls.append("PRAGMA legacy_alter_table=OFF;")
|
||||
sqls.append(
|
||||
"PRAGMA legacy_alter_table={};".format(
|
||||
"ON" if legacy_alter_table_was_on else "OFF"
|
||||
)
|
||||
)
|
||||
# Re-add existing indexes
|
||||
for index in self.indexes:
|
||||
if index.origin != "pk":
|
||||
|
|
|
|||
|
|
@ -1049,3 +1049,17 @@ def test_transform_with_view_in_open_transaction(fresh_db):
|
|||
"select sql from sqlite_master where name = 'dogs_view'"
|
||||
).fetchone()[0]
|
||||
assert view_sql == "CREATE VIEW dogs_view as select id, name from dogs"
|
||||
|
||||
|
||||
def test_transform_restores_legacy_alter_table_setting(fresh_db):
|
||||
dogs = fresh_db["dogs"]
|
||||
dogs.insert({"id": 1, "name": "Cleo"}, pk="id")
|
||||
# Default is OFF, reset to OFF afterwards
|
||||
dogs.transform(types={"name": str})
|
||||
assert fresh_db.execute("PRAGMA legacy_alter_table").fetchone()[0] == 0
|
||||
# If the connection has it ON, it should be restored to ON
|
||||
fresh_db.execute("PRAGMA legacy_alter_table=ON")
|
||||
sqls = dogs.transform_sql(types={"name": str}, tmp_suffix="suffix")
|
||||
assert sqls[-1] == "PRAGMA legacy_alter_table=ON;"
|
||||
dogs.transform(types={"name": str})
|
||||
assert fresh_db.execute("PRAGMA legacy_alter_table").fetchone()[0] == 1
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue