Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SQLite Triggers aren't re-created after column change #2700

Open
goknsh opened this issue Apr 19, 2024 · 0 comments
Open

SQLite Triggers aren't re-created after column change #2700

goknsh opened this issue Apr 19, 2024 · 0 comments
Assignees

Comments

@goknsh
Copy link

goknsh commented Apr 19, 2024

We start with this schema:

CREATE TABLE users (
	id TEXT NOT NULL PRIMARY KEY,
	username TEXT NOT NULL UNIQUE,
	updated_at integer default (unixepoch()) not null
) WITHOUT ROWID;

CREATE TRIGGER update_users_updated_at AFTER UPDATE OF username ON users FOR EACH ROW
	BEGIN
		UPDATE users SET updated_at = unixepoch() WHERE id = NEW.id;
	END;

migrate diff generates the following migration:

-- Create "users" table
CREATE TABLE `users` (`id` text NOT NULL, `username` text NOT NULL, `updated_at` integer NOT NULL DEFAULT (unixepoch()), PRIMARY KEY (`id`)) WITHOUT ROWID;
-- Create index "users_username" to table: "users"
CREATE UNIQUE INDEX `users_username` ON `users` (`username`);
-- Create trigger "update_users_updated_at"
CREATE TRIGGER `update_users_updated_at` AFTER UPDATE OF `username` ON `users` FOR EACH ROW BEGIN
		UPDATE users SET updated_at = unixepoch() WHERE id = NEW.id;
	END;

Next, we rename a column on the users table:

CREATE TABLE users (
	user_id TEXT NOT NULL PRIMARY KEY,
	username TEXT NOT NULL UNIQUE,
	updated_at integer default (unixepoch()) not null
) WITHOUT ROWID;

CREATE TRIGGER update_users_updated_at AFTER UPDATE OF username ON users FOR EACH ROW
	BEGIN
		UPDATE users SET updated_at = unixepoch() WHERE id = NEW.id;
	END;

migrate diff generates the following incorrect migration:

-- Disable the enforcement of foreign-keys constraints
PRAGMA foreign_keys = off;
-- Create "new_users" table
CREATE TABLE `new_users` (`user_id` text NOT NULL, `username` text NOT NULL, `updated_at` integer NOT NULL DEFAULT (unixepoch()), PRIMARY KEY (`user_id`)) WITHOUT ROWID;
-- Copy rows from old table "users" to new temporary table "new_users"
INSERT INTO `new_users` (`username`, `updated_at`) SELECT `username`, `updated_at` FROM `users`;
-- Drop "users" table after copying rows
DROP TABLE `users`;
-- Rename temporary table "new_users" to "users"
ALTER TABLE `new_users` RENAME TO `users`;
-- Create index "users_username" to table: "users"
CREATE UNIQUE INDEX `users_username` ON `users` (`username`);
-- Enable back the enforcement of foreign-keys constraints
PRAGMA foreign_keys = on;

The SQLite manual says:

Triggers are automatically dropped when the table that they are associated with (the table-name table) is dropped. However if the trigger actions reference other tables, the trigger is not dropped or modified if those other tables are dropped or modified.

https://www.sqlite.org/lang_createtrigger.html#description

So, in this particular situation, the trigger should be re-created after the table has been renamed. Also, I noticed that if I rename username to uname in both the table definition and trigger, it works as expected.

@a8m a8m self-assigned this Apr 20, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants