Description
Problem
In the following cases (possibly more) any indexes on the column are dropped, but aren't recreated afterwards:
(a) when a column is made null-able (i.e. adding null=True
)
(b) when a column is renamed
(c) when a table is renamed
This is quite a major issue because it is silently leaving the database in the wrong state - the migration doesn't fail, but now certain columns with db_index=True
won't actually have an index which could cause very slow queries.
Cause
As far as I can see this is a triple-regression introduced (before this fork was created) by 2e60754 (ESSolutions/django-mssql-backend#24).
That commit added new calls to _delete_indexes
in 2 places within _alter_field
causing the first two cases listed above:
(a) ESSolutions/django-mssql-backend@2e6075456a#diff-e4c1520d8b49ccbf46382bd2eed4e740R400
(b) ESSolutions/django-mssql-backend@2e6075456a#diff-e4c1520d8b49ccbf46382bd2eed4e740R334-R335
and added an explicit index deletion here in alter_db_table
before renaming a table causing the third case:
(c) ESSolutions/django-mssql-backend@2e6075456a#diff-e4c1520d8b49ccbf46382bd2eed4e740R222-R225
but in none of those cases is the index re-instated afterwards, even if the field still has db_index=True
. Index restoration only happens in certain specific cases (e.g. type change / removal of nullability) which doesn't include the above 3 cases.
Reproduction
I've added 3 tests in #49 which fail due to the bugs described above, but pass if run on older versions like django-mssql-backend
v2.4.2 (before ESSolutions/django-mssql-backend#24 was merged).
History
I previously filed this on the project from which this was forked ESSolutions/django-mssql-backend#58 - given there was no feedback to my proposed solution there, I hope it's ok to file an equivalent issue here. Hopefully this more official project might be able to provide some insight. This was my comment (the only one on that issue) re possible fixes:
Considering how to solve this, one approach would be to expand the condition under
# Restore an index
, or to start explicitly keeping track of which indexes have been dropped and need re-creating.However before that we should ask: is it actually necessary for all indexes to be dropped in these 3 cases?
If it can be avoided then it will save wasting time during migration of a large table. MS SQL Server seems to allow those 3 operations to occur while the index is there (it didn't explode in those cases using v2.4.2).
@OskarPersson do you know what the reasons were for adding all these "delete index before doing X" in 2e60754?