tortoise / aerich

A database migrations tool for TortoiseORM, ready to production.
https://github.com/tortoise/aerich
Apache License 2.0
808 stars 91 forks source link

error downgrading unique index #237

Open abe-winter opened 2 years ago

abe-winter commented 2 years ago

When I add a unique index to a field, the index name for the downgrade command has the wrong prefix (uid vs idx).

This is the migration:

-- upgrade --
CREATE UNIQUE INDEX "uid_account_name_d49e11" ON "account" ("name");
-- downgrade --
DROP INDEX "idx_account_name_d49e11";

And this is the error:

tortoise.exceptions.OperationalError: index "idx_account_name_d49e11" does not exist

(because uid + idx don't agree above)

versions: aerich==0.6.2 tortoise-orm==0.18.1

This isn't an urgent bug (it's easy to workaround by editing the migration file).

why it fails

the top-level migrate command runs diff_models with (last, new) and then (new, last), here:

https://github.com/tortoise/aerich/blob/f15cbaf9e0269fca88741fae135bc7952fafd444/aerich/migrate.py#L132-L133

unique in the changed fields handler is from new_data_field:

https://github.com/tortoise/aerich/blob/f15cbaf9e0269fca88741fae135bc7952fafd444/aerich/migrate.py#L419

but when invoked from L133, new_data_field is actually the old data field, and unique = False.

And this mixes up uid vs idx prefix in ddl here:

https://github.com/tortoise/aerich/blob/f15cbaf9e0269fca88741fae135bc7952fafd444/aerich/ddl/__init__.py#L184

possible fix

If I understand the issue correctly, you can change migrate.py L419 like:

- unique = new_data_field.get("unique")
+ unique = new_data_field.get("unique") if upgrade else old_data_field.get("unique")

This is for the case of (no_index -> unique_index). The case of (normal_index -> unique_Index) is more complicated.

related issues

195