Triggers bind to their table by name string: RENAME TABLE silently detaches them, and the orphan rebinds to any future table with the old name
- Dominant language
- Go
- Stars
- 24.4k
- Forks
- 873
- Avg merge
- 1d 8h
- Merged PRs (30d)
- 120
Description
Triggers are associated with their table by the stored name string in `dolt_schemas`, not by table identity. Three consequences, escalating in severity — the third silently rewrites data the user never asked a trigger to touch.
Related: #11587 (`information_schema.triggers` errors after a column rename). Same underlying family — the trigger body is stored as raw text and resolved by name at use time — but that issue is introspection-only; this one changes data behavior.
## 1. `RENAME TABLE` detaches triggers, which silently stop firing
```sql
create table t(k int primary key, n int);
create trigger tg0 before insert on t for each row set new.n = 42;
rename table t to t9;
insert into t9 values (1, 0);
select n from t9;
```
```
n
0 -- MySQL: 42. The trigger silently did not fire.
```
MySQL keeps triggers attached through `RENAME TABLE`. Dolt leaves the `dolt_schemas` row naming `t`, so the trigger detaches without any error or warning.
## 2. While the orphan exists, trigger introspection errors database-wide
```sql
show triggers;
-- table not found: t
select trigger_name from information_schema.triggers;
-- table not found: t
```
One orphaned row makes every trigger unlistable.
## 3. The orphan rebinds to any future table with the old name
Continuing the same session:
```sql
create table t(k int primary key, n int); -- a brand-new, unrelated table
insert into t values (1, 0);
select n from t;
```
```
n
42 -- tg0 revived and rewrote the new table's data
```
A trigger the user never created on this table fires on it. Anyone who renames a table away and later reuses the name inherits dormant behavior from the old one.
## Merges reach the same state across branches
No single-branch misuse is needed. Branch A creates a trigger on `t`; branch B drops (or renames) `t`; the merge succeeds and composes them:
```sql
-- after merging: show tables is empty, yet
select type,name,fragment from dolt_schemas;
-- trigger, tg0, create trigger tg0 after insert on t for each row ...
show triggers;
-- table not found: t
```
MySQL semantics are that a trigger cannot exist without its table (`DROP TABLE` drops its triggers; `RENAME TABLE` carries them along). A schema conflict on the merge, or applying MySQL's own rules, would both avoid the orphan; today the merge quietly manufactures a state MySQL cannot represent, with consequence 3 waiting downstream.
Found while building DoltLite's schema-merge oracle against Dolt (dolthub/doltlite#2333); reproduced on the version below.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start by reproducing the RENAME TABLE, trigger introspection, name reuse, and merge cases described in the issue, then inspect the dolt_schemas rows and the paths behind SHOW TRIGGERS and information_schema.triggers. Done means triggers remain associated with the correct table through renames and merges, orphaned triggers cannot affect future tables, and introspection remains usable.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, mysql
- Domain
- databases
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 42/100