Fixed #35373 -- Fixed a crash when indexing a generated field on SQLite.

Generated fields have to be excluded from the INSERT query against the remade
table including the index.

Thanks Moshe Dicker for the report, David Sanders and Mariusz Felisiak for the
review.
This commit is contained in:
Simon Charette 2024-04-16 00:11:36 -04:00 committed by Sarah Boyce
parent 47c608202a
commit d048f0d311
3 changed files with 40 additions and 1 deletions

View File

@ -150,6 +150,9 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
body.pop(old_field.name, None)
mapping.pop(old_field.column, None)
body[new_field.name] = new_field
rename_mapping[old_field.name] = new_field.name
if new_field.generated:
continue
if old_field.null and not new_field.null:
if new_field.db_default is NOT_PROVIDED:
default = self.prepare_default(self.effective_default(new_field))
@ -162,7 +165,6 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
mapping[new_field.column] = case_sql
else:
mapping[new_field.column] = self.quote_name(old_field.column)
rename_mapping[old_field.name] = new_field.name
# Remove any deleted fields
if delete_field:
del body[delete_field.name]

View File

@ -16,3 +16,7 @@ Bugfixes
* Fixed a compatibility issue encountered in Python 3.11.9+ and 3.12.3+ when
validating email max line lengths with content decoded using the
``surrogateescape`` error handling scheme (:ticket:`35361`).
* Fixed a bug in Django 5.0 that caused a crash when applying migrations
including alterations to ``GeneratedField`` such as setting ``db_index=True``
on SQLite (:ticket:`35373`).

View File

@ -928,6 +928,39 @@ class SchemaTests(TransactionTestCase):
self.assertEqual(obj.generated, "foo%")
self.assertIs(obj.contains_foo, True)
@isolate_apps("schema")
@skipUnlessDBFeature("supports_stored_generated_columns")
def test_alter_generated_field(self):
class GeneratedFieldIndexedModel(Model):
number = IntegerField(default=1)
generated = GeneratedField(
expression=F("number"),
db_persist=True,
output_field=IntegerField(),
)
class Meta:
app_label = "schema"
with connection.schema_editor() as editor:
editor.create_model(GeneratedFieldIndexedModel)
old_field = GeneratedFieldIndexedModel._meta.get_field("generated")
new_field = GeneratedField(
expression=F("number"),
db_persist=True,
db_index=True,
output_field=IntegerField(),
)
new_field.contribute_to_class(GeneratedFieldIndexedModel, "generated")
with connection.schema_editor() as editor:
editor.alter_field(GeneratedFieldIndexedModel, old_field, new_field)
self.assertIn(
"generated", self.get_indexes(GeneratedFieldIndexedModel._meta.db_table)
)
@isolate_apps("schema")
def test_add_auto_field(self):
class AddAutoFieldModel(Model):