Skip to content

Commit

Permalink
[3.2.x] Fixed #33194 -- Fixed migrations when altering a field with f…
Browse files Browse the repository at this point in the history
…unctional indexes on SQLite.

This adjusts Expressions.rename_table_references() to only update alias
when needed.

Regression in 83fcfc9.

Co-authored-by: Simon Charette <charettes@users.noreply.github.com>

Backport of 86971c4 from main.
  • Loading branch information
hannseman authored and felixxm committed Oct 18, 2021
1 parent fdc1c64 commit f5802a2
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 6 deletions.
6 changes: 1 addition & 5 deletions django/db/backends/ddl_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,11 +212,7 @@ def __init__(self, table, expressions, compiler, quote_value):
def rename_table_references(self, old_table, new_table):
if self.table != old_table:
return
expressions = deepcopy(self.expressions)
self.columns = []
for col in self.compiler.query._gen_cols([expressions]):
col.alias = new_table
self.expressions = expressions
self.expressions = self.expressions.relabeled_clone({old_table: new_table})
super().rename_table_references(old_table, new_table)

def rename_column_references(self, table, old_column, new_column):
Expand Down
3 changes: 2 additions & 1 deletion docs/releases/3.2.9.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ Django 3.2.9 fixes several bugs in 3.2.8 and adds compatibility with Python
Bugfixes
========

* ...
* Fixed a bug in Django 3.2 that caused a migration crash on SQLite when
altering a field with a functional index (:ticket:`33194`).
22 changes: 22 additions & 0 deletions tests/backends/test_ddl_references.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.db.models import ExpressionList, F
from django.db.models.functions import Upper
from django.db.models.indexes import IndexExpression
from django.db.models.sql import Query
from django.test import SimpleTestCase, TransactionTestCase

from .models import Person
Expand Down Expand Up @@ -229,6 +230,27 @@ def test_rename_table_references(self):
str(self.expressions),
)

def test_rename_table_references_without_alias(self):
compiler = Query(Person, alias_cols=False).get_compiler(connection=connection)
table = Person._meta.db_table
expressions = Expressions(
table=table,
expressions=ExpressionList(
IndexExpression(Upper('last_name')),
IndexExpression(F('first_name')),
).resolve_expression(compiler.query),
compiler=compiler,
quote_value=self.editor.quote_value,
)
expressions.rename_table_references(table, 'other')
self.assertIs(expressions.references_table(table), False)
self.assertIs(expressions.references_table('other'), True)
expected_str = '(UPPER(%s)), %s' % (
self.editor.quote_name('last_name'),
self.editor.quote_name('first_name'),
)
self.assertEqual(str(expressions), expected_str)

def test_rename_column_references(self):
table = Person._meta.db_table
self.expressions.rename_column_references(table, 'first_name', 'other')
Expand Down
19 changes: 19 additions & 0 deletions tests/migrations/test_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -2010,6 +2010,25 @@ def test_remove_func_index(self):
self.assertEqual(definition[1], [])
self.assertEqual(definition[2], {'model_name': 'Pony', 'name': index_name})

@skipUnlessDBFeature('supports_expression_indexes')
def test_alter_field_with_func_index(self):
app_label = 'test_alfuncin'
index_name = f'{app_label}_pony_idx'
table_name = f'{app_label}_pony'
project_state = self.set_up_test_model(
app_label,
indexes=[models.Index(Abs('pink'), name=index_name)],
)
operation = migrations.AlterField('Pony', 'pink', models.IntegerField(null=True))
new_state = project_state.clone()
operation.state_forwards(app_label, new_state)
with connection.schema_editor() as editor:
operation.database_forwards(app_label, editor, project_state, new_state)
self.assertIndexNameExists(table_name, index_name)
with connection.schema_editor() as editor:
operation.database_backwards(app_label, editor, new_state, project_state)
self.assertIndexNameExists(table_name, index_name)

def test_alter_field_with_index(self):
"""
Test AlterField operation with an index to ensure indexes created via
Expand Down

0 comments on commit f5802a2

Please sign in to comment.