Repository navigation
fix(drop): drop a PostgreSQL enum type only when no column uses it (2.3) - #1633
Conversation
On PostgreSQL, dropping a table could drop columns of other tables, with their data. An enum attribute is declared with an enum type named by its values, so every column in the schema with the same values shares one type. `drop_quick()` dropped the table's enum types afterwards with `DROP TYPE ... CASCADE`, and CASCADE also dropped every other column of that type. Two tables that both declare `species : enum('mouse', 'rat')` share a type, and dropping one took the other's `species` column. Every jobs table has the same `status` enum, so dropping one jobs table removed `status` from all the others in the schema. MySQL has no enum types and was not affected.
An enum type is now dropped only when no column uses it any more, and the statement no longer cascades, so a type still in use is never dropped with its columns.
The new tests, on both backends, drop one of two tables that share an enum and check that the other keeps its column and values, that the type is removed once neither table remains, and that dropping one jobs table leaves another's status column and jobs in place. Both fail on PostgreSQL before this change.
(cherry picked from commit 7e9cae9)
MilagrosMarin
left a comment
There was a problem hiding this comment.
LGTM. The diff matches #1632 line for line, and the fix is sound: without CASCADE, a type still in use can't take other tables' columns with it, and checking pg_attribute first avoids sending a DROP TYPE that would fail. The two integration tests cover both cases from #1630, the shared species enum and the jobs tables' status column.
#1632 itself is still open without a review, so I'd merge it before this one, to keep maint/2.3 from getting ahead of master.
Minor, not blocking: '…'::regtype raises when the type no longer exists. The except catches that, but inside a transaction it would abort it the same way a failed DROP TYPE would. That only matters if enum_types_to_drop can list a type twice or one that is already gone; to_regtype(…) would return NULL instead.
Backport of #1632 to
maint/2.3for v2.3.5, cherry-picked unchanged.On PostgreSQL, dropping a table could drop columns of other tables, with their data. An enum attribute is declared with an enum type named by its values, so every column in the schema with the same values shares one type.
drop_quick()dropped the table's enum types afterwards withDROP TYPE ... CASCADE, and CASCADE also dropped every other column of that type. Two tables that both declarespecies : enum('mouse', 'rat')share a type, and dropping one took the other'sspeciescolumn. Every jobs table has the samestatusenum, so dropping one jobs table removedstatusfrom all the others in the schema. MySQL has no enum types and was not affected.An enum type is now dropped only when no column uses it any more, and the statement no longer cascades, so a type still in use is never dropped with its columns.
The new tests, on both backends, drop one of two tables that share an enum and check that the other keeps its column and values, that the type is removed once neither table remains, and that dropping one jobs table leaves another's status column and jobs in place. Both fail on PostgreSQL before this change.
Fixes #1630.