fix issue #1: transform-fails-to-drop-column-if-table-is-part

This commit is contained in:
libra-exla[bot] 2026-06-02 00:11:23 +00:00
commit 52fc6fc115
2 changed files with 74 additions and 0 deletions

View file

@ -1905,6 +1905,17 @@ class Table(Queryable):
column_order=column_order, column_order=column_order,
keep_table=keep_table, keep_table=keep_table,
) )
views = self.db.execute(
"select name, sql from sqlite_master where type = 'view' "
"and sql is not null order by rowid"
).fetchall()
view_triggers = []
if views:
view_triggers = self.db.execute(
"select name, sql from sqlite_master where type = 'trigger' "
"and sql is not null and tbl_name in "
"(select name from sqlite_master where type = 'view') order by rowid"
).fetchall()
pragma_foreign_keys_was_on = self.db.execute("PRAGMA foreign_keys").fetchone()[ pragma_foreign_keys_was_on = self.db.execute("PRAGMA foreign_keys").fetchone()[
0 0
] ]
@ -1912,11 +1923,26 @@ class Table(Queryable):
if pragma_foreign_keys_was_on: if pragma_foreign_keys_was_on:
self.db.execute("PRAGMA foreign_keys=0;") self.db.execute("PRAGMA foreign_keys=0;")
with self.db.conn: with self.db.conn:
if views and not self.db.conn.in_transaction:
self.db.execute("BEGIN;")
for view_name, _ in views:
self.db.execute("DROP VIEW {}".format(quote_identifier(view_name)))
for sql in sqls: for sql in sqls:
self.db.execute(sql) self.db.execute(sql)
# Run the foreign_key_check before we commit # Run the foreign_key_check before we commit
if pragma_foreign_keys_was_on: if pragma_foreign_keys_was_on:
self.db.execute("PRAGMA foreign_key_check;") self.db.execute("PRAGMA foreign_key_check;")
for view_name, view_sql in views:
try:
self.db.execute(view_sql)
except sqlite3.OperationalError as e:
raise TransformError(
f"View '{view_name}' could not be recreated after transforming table '{self.name}'. "
"It may reference columns that were dropped or renamed. "
"You must recreate this view manually."
) from e
for _, trigger_sql in view_triggers:
self.db.execute(trigger_sql)
finally: finally:
if pragma_foreign_keys_was_on: if pragma_foreign_keys_was_on:
self.db.execute("PRAGMA foreign_keys=1;") self.db.execute("PRAGMA foreign_keys=1;")

View file

@ -659,3 +659,51 @@ def test_transform_with_unique_constraint_implicit_index(fresh_db):
"You must manually drop this index prior to running this transformation and manually recreate the new index after running this transformation." "You must manually drop this index prior to running this transformation and manually recreate the new index after running this transformation."
in str(excinfo.value) in str(excinfo.value)
) )
def test_transform_recreates_views(fresh_db):
dogs = fresh_db["dogs"]
dogs.insert({"id": 1, "name": "Cleo", "age": 5}, pk="id")
fresh_db.create_view("dog_names", "select id, name from dogs")
dogs.transform(drop={"age"})
assert list(fresh_db.query("select * from dog_names")) == [
{"id": 1, "name": "Cleo"}
]
def test_transform_recreates_triggers_on_views(fresh_db):
dogs = fresh_db["dogs"]
dogs.insert({"id": 1, "name": "Cleo", "age": 5}, pk="id")
fresh_db.execute("create table dog_log (id integer primary key, name text)")
fresh_db.create_view("dog_names", "select id, name from dogs")
fresh_db.execute("""
create trigger dog_names_insert
instead of insert on dog_names
begin
insert into dog_log (id, name) values (new.id, new.name);
end;
""")
dogs.transform(drop={"age"})
fresh_db.execute(
"insert into dog_names (id, name) values (?, ?)",
(2, "Mabel"),
)
assert list(fresh_db["dog_log"].rows) == [{"id": 2, "name": "Mabel"}]
def test_transform_does_not_execute_unrelated_views(fresh_db):
dogs = fresh_db["dogs"]
dogs.insert({"id": 1, "name": "Cleo", "age": 5}, pk="id")
fresh_db["other"].insert({"x": 1})
fresh_db.execute(
"create view other_values as select app_func(x) as value from other"
)
dogs.transform(drop={"age"})
assert "other_values" in fresh_db.view_names()