Disclaimer: I haven't yet tried this with the pre-release version of sqlite-3.25.1, but I wanted to report it before the 24 hours of that release notice expired.

In sqlite-3.25.0, the release notes say the following:

"Fix table rename feature so that it also updates references to the renamed table in triggers and views."

This is mentioned again on https://www.sqlite.org/lang_altertable.html:

"Beginning with release 3.25.0 (2018-09-15), references to the table within trigger bodies and view definitions are also renamed."

However, because of this change, the "completely general" procedure on the ALTER TABLE page no longer works.

For example, the following works in sqlite-3.24.0 but not in sqlite-3.25.0:


-- Create a pair of tables related by a trigger.
create table t1(a integer not null primary key, b text not null);
create table t2(c integer primary key, d text);

-- Create a simple trigger on t1 that uses t2.
create trigger t1_trigger
after insert on t1
for each row
begin
  insert into t2 (c, d) values (new.a, new.b);
end;

-- Demonstrate that it works.
select 'Before modifications' as comment;
insert into t1 values (1, 'aaa');
select * from t1;
select * from t2;

-- Follow the general procedure from
-- https://www.sqlite.org/lang_altertable.html
pragma foreign_keys = off;
begin transaction;
-- Change c and d to be "not null".
create table new_t2(c integer not null primary key, d text not null);

-- Copy data.
insert into new_t2 (c, d) select c, d from t2;

-- Drop old table.
drop table t2;

-- Rename table.
select 'About to rename new_t2 to t2' as comment;
alter table new_t2 rename to t2;

-- Check FKs.
pragma foreign_key_check;

-- Finish.
commit transaction;
pragma foreign_keys = on;

-- Demonstrate that it still works.
select 'After modifications' as comment;
insert into t1 values (2, 'bbb');
select * from t1;
select * from t2;


Output in sqlite-3.24.0:

$ ./sqlite3 :memory: < ~/external/sqlite3/trigger.sql
Before modifications
1|aaa
1|aaa
About to rename new_t2 to t2
After modifications
1|aaa
2|bbb
1|aaa
2|bbb

Output in sqlite-3.25.0:

$ ./sqlite3 :memory: < ~/external/sqlite3/trigger.sql
Before modifications
1|aaa
1|aaa
About to rename new_t2 to t2
Error: near line 34: error in trigger t1_trigger: no such table: main.t2
After modifications
Error: near line 45: no such table: main.t2
1|aaa
Error: near line 47: no such table: t2

Note that the failure occurs before the ALTER TABLE page's procedure says to re-create any triggers. But even so, in this case, the triggers are "on" t1, not t2, so in previous SQLite versions they did not need to be re-created anyway.

It seems like the new ALTER TABLE behaviour was intended to be an enhancement that makes it easier to make schema changes and that this is an unexpected consequence of the change. Personally, I found the older behaviour easier to work with: You re-created triggers on the table you were recreating, but left any (symbolic) references to the recreated table from other tables' triggers alone. Now, it looks like I will have to drop all triggers in the database that reference the recreated table and recreate them all, which seems to be the opposite of the intended effect. This also means going back and rewriting previous database schema patches that no longer run under sqlite-3.25.0.

Perhaps at least there should be a pragma or configuration flag to turn this new behaviour off?

--
Brad Spencer
_______________________________________________
sqlite-users mailing list
sqlite-users@mailinglists.sqlite.org
http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users

Reply via email to