Refs #32502 -- Avoided table rebuild when removing fields on SQLite 3.35.5+.
ALTER TABLE ... DROP COLUMN was introduced in SQLite 3.35+ however a data corruption issue was fixed in SQLite 3.35.5.
This commit is contained in:
parent
d113b5a837
commit
3702819227
|
@ -28,6 +28,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
|
|||
has_case_insensitive_like = True
|
||||
# Is "ALTER TABLE ... RENAME COLUMN" supported?
|
||||
can_alter_table_rename_column = Database.sqlite_version_info >= (3, 25, 0)
|
||||
# Is "ALTER TABLE ... DROP COLUMN" supported?
|
||||
can_alter_table_drop_column = Database.sqlite_version_info >= (3, 35, 5)
|
||||
supports_parentheses_in_compound = False
|
||||
# Deferred constraint checks can be emulated on SQLite < 3.20 but not in a
|
||||
# reasonably performant way.
|
||||
|
|
|
@ -18,6 +18,7 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||
"REFERENCES %(to_table)s (%(to_column)s) DEFERRABLE INITIALLY DEFERRED"
|
||||
)
|
||||
sql_create_column_inline_fk = sql_create_inline_fk
|
||||
sql_delete_column = "ALTER TABLE %(table)s DROP COLUMN %(column)s"
|
||||
sql_create_unique = "CREATE UNIQUE INDEX %(name)s ON %(table)s (%(columns)s)"
|
||||
sql_delete_unique = "DROP INDEX %(name)s"
|
||||
|
||||
|
@ -400,6 +401,15 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
|
|||
if field.remote_field.through._meta.auto_created:
|
||||
self.delete_model(field.remote_field.through)
|
||||
# For explicit "through" M2M fields, do nothing
|
||||
elif (
|
||||
self.connection.features.can_alter_table_drop_column
|
||||
# Primary keys, unique fields, and foreign keys are not
|
||||
# supported in ALTER TABLE DROP COLUMN.
|
||||
and not field.primary_key
|
||||
and not field.unique
|
||||
and not (field.remote_field and field.db_constraint)
|
||||
):
|
||||
super().remove_field(model, field)
|
||||
# For everything else, remake.
|
||||
else:
|
||||
# It might not actually have a column behind it
|
||||
|
|
|
@ -789,6 +789,24 @@ class SchemaTests(TransactionTestCase):
|
|||
# Introspection treats BLOBs as TextFields
|
||||
self.assertEqual(columns["bits"][0], "TextField")
|
||||
|
||||
def test_remove_field(self):
|
||||
with connection.schema_editor() as editor:
|
||||
editor.create_model(Author)
|
||||
with CaptureQueriesContext(connection) as ctx:
|
||||
editor.remove_field(Author, Author._meta.get_field("name"))
|
||||
columns = self.column_classes(Author)
|
||||
self.assertNotIn("name", columns)
|
||||
if getattr(connection.features, "can_alter_table_drop_column", True):
|
||||
# Table is not rebuilt.
|
||||
self.assertIs(
|
||||
any("CREATE TABLE" in query["sql"] for query in ctx.captured_queries),
|
||||
False,
|
||||
)
|
||||
self.assertIs(
|
||||
any("DROP TABLE" in query["sql"] for query in ctx.captured_queries),
|
||||
False,
|
||||
)
|
||||
|
||||
def test_alter(self):
|
||||
"""
|
||||
Tests simple altering of fields
|
||||
|
|
Loading…
Reference in New Issue