Restore Meta.indexes after RenameField and AlterField - #584
Open
Rob Berwick (robberwick) wants to merge 2 commits into
Open
Restore Meta.indexes after RenameField and AlterField#584Rob Berwick (robberwick) wants to merge 2 commits into
Meta.indexes after RenameField and AlterField#584Rob Berwick (robberwick) wants to merge 2 commits into
Conversation
…dexes tests The two tests covering the scenario where RenameField and AlterField (type change or nullability change) occur in the same migration were previously marked @expectedfailure because the fix was not yet in place. Remove the @expectedfailure decorators so that these tests will fail (RED) until the corresponding fix in schema.py is committed.
…ld in same migration Django's ProjectState.rename_field() updates model fields but does NOT update Index.fields in Meta.indexes, leaving stale field names after a rename. When AlterField then runs in the same migration, _delete_indexes() and the restoration phase would call model._meta.get_field() with the old name and raise FieldDoesNotExist. Fix in three locations in schema.py: - _delete_indexes(): add _resolve_column() helper that catches FieldDoesNotExist and falls back to new_field.column; also check new_field.column membership - _alter_field() collection phase: per-field try/except when building index_columns_list - _alter_field() restoration phase: reconstruct stale Index objects via deconstruct() with corrected field names so Index.__init__ properly derives fields_orders (Index.create_sql uses fields_orders, not fields, to resolve field names to columns)
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Contributor
There was a problem hiding this comment.
Pull request overview
This PR fixes a Django migration edge case in the SQL Server backend where Meta.indexes entries could be dropped (or index handling could error) when a RenameField is followed by an AlterField (type/nullability) in the same migration, by making index drop/restore logic resilient to stale field names (issue #499).
Changes:
- Updates
mssql/schema.pyto resolve staleIndex.fieldsnames when determining which indexes to drop/restore and when generatingCREATE INDEXSQL. - Rebuilds
Indexinstances with corrected field names before callingcreate_sql()so explicit names/options/ordering are preserved. - Enables the existing regression tests by removing
@expectedFailureand updating docstrings to reference #499.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
mssql/schema.py |
Adjusts index deletion/restoration logic in _alter_field() / _delete_indexes() to handle stale index field names after rename+alter sequences. |
testapp/tests/test_indexes.py |
Turns previously expected-failure scenarios into active regressions for rename+type-change and rename+nullability-change. |
Suppressed comments (1)
mssql/schema.py:999
- The stale-field detection checks model._meta.get_field(field_name) against raw values from index.fields. For ordered indexes, those raw values can start with '-' (e.g. '-a'), which will always raise FieldDoesNotExist even when the underlying field exists, causing unnecessary cloning/reconstruction.
for field_name in index.fields:
try:
model._meta.get_field(field_name)
except FieldDoesNotExist:
has_stale_fields = True
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+965
to
+969
| for field_name in index.fields_orders: | ||
| try: | ||
| index_columns_list.append(model._meta.get_field(field_name).column) | ||
| except FieldDoesNotExist: | ||
| index_columns_list.append(new_field.column) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #499. A migration that renames a field and then changes its type or nullability in the same migration could drop a
Meta.indexesindex permanently or raiseFieldDoesNotExist.ProjectState.rename_field()updates the model field name but leavesIndex.fieldswith the original name. The schema editor subsequently attempted to resolve that stale name against the renamed model state.new_field.columnwhile locating indexes to drop.Indexinstances with the current field name before generating theCREATE INDEXSQL, preserving index options, explicit names, and ordering.