summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Charette <charette.s@gmail.com>2016-05-24 15:38:01 -0400
committerSimon Charette <charette.s@gmail.com>2017-06-21 00:26:30 -0400
commitb1cbbe926789bcfc2e118c7d7c7a0f30fab5248a (patch)
tree9b78889db67d09d5325d04d72dc396c364d8d92c
parentb50815ee418b38e719476c2d5f6e2bc69f686927 (diff)
Refs #25530 -- Deleted deferred SQL references on delete operation.
-rw-r--r--django/db/backends/base/schema.py8
-rw-r--r--django/db/backends/sqlite3/schema.py9
-rw-r--r--tests/schema/tests.py22
3 files changed, 29 insertions, 10 deletions
diff --git a/django/db/backends/base/schema.py b/django/db/backends/base/schema.py
index e31251ae81..91ee3dac22 100644
--- a/django/db/backends/base/schema.py
+++ b/django/db/backends/base/schema.py
@@ -314,6 +314,10 @@ class BaseDatabaseSchemaEditor:
self.execute(self.sql_delete_table % {
"table": self.quote_name(model._meta.db_table),
})
+ # Remove all deferred statements referencing the deleted table.
+ for sql in list(self.deferred_sql):
+ if isinstance(sql, Statement) and sql.references_table(model._meta.db_table):
+ self.deferred_sql.remove(sql)
def add_index(self, model, index):
"""Add an index on a model."""
@@ -456,6 +460,10 @@ class BaseDatabaseSchemaEditor:
# Reset connection if required
if self.connection.features.connection_persists_old_columns:
self.connection.close()
+ # Remove all deferred statements referencing the deleted table.
+ for sql in list(self.deferred_sql):
+ if isinstance(sql, Statement) and sql.references_column(model._meta.db_table, field.column):
+ self.deferred_sql.remove(sql)
def alter_field(self, model, old_field, new_field, strict=False):
"""
diff --git a/django/db/backends/sqlite3/schema.py b/django/db/backends/sqlite3/schema.py
index 5517d78a97..3bf71e071a 100644
--- a/django/db/backends/sqlite3/schema.py
+++ b/django/db/backends/sqlite3/schema.py
@@ -190,11 +190,6 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
# Rename the old table to make way for the new
self.alter_db_table(model, temp_model._meta.db_table, model._meta.db_table)
- # Remove all deferred statements referencing the temporary table.
- for sql in list(self.deferred_sql):
- if isinstance(sql, Statement) and sql.references_table(temp_model._meta.db_table):
- self.deferred_sql.remove(sql)
-
# Create a new table with the updated schema.
self.create_model(temp_model)
@@ -226,6 +221,10 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor):
self.execute(self.sql_delete_table % {
"table": self.quote_name(model._meta.db_table),
})
+ # Remove all deferred statements referencing the deleted table.
+ for sql in list(self.deferred_sql):
+ if isinstance(sql, Statement) and sql.references_table(model._meta.db_table):
+ self.deferred_sql.remove(sql)
def add_field(self, model, field):
"""
diff --git a/tests/schema/tests.py b/tests/schema/tests.py
index f4612a5dee..b889f6cda1 100644
--- a/tests/schema/tests.py
+++ b/tests/schema/tests.py
@@ -195,14 +195,15 @@ class SchemaTests(TransactionTestCase):
"""
Tries creating a model's table, and then deleting it.
"""
- # Create the table
with connection.schema_editor() as editor:
+ # Create the table
editor.create_model(Author)
- # The table is there
- list(Author.objects.all())
- # Clean up that table
- with connection.schema_editor() as editor:
+ # The table is there
+ list(Author.objects.all())
+ # Clean up that table
editor.delete_model(Author)
+ # No deferred SQL should be left over.
+ self.assertEqual(editor.deferred_sql, [])
# The table is gone
with self.assertRaises(DatabaseError):
list(Author.objects.all())
@@ -379,6 +380,17 @@ class SchemaTests(TransactionTestCase):
self.assertEqual(columns['age'][0], "IntegerField")
self.assertEqual(columns['age'][1][6], True)
+ def test_add_field_remove_field(self):
+ """
+ Adding a field and removing it removes all deferred sql referring to it.
+ """
+ with connection.schema_editor() as editor:
+ # Create a table with a unique constraint on the slug field.
+ editor.create_model(Tag)
+ # Remove the slug column.
+ editor.remove_field(Tag, Tag._meta.get_field('slug'))
+ self.assertEqual(editor.deferred_sql, [])
+
def test_add_field_temp_default(self):
"""
Tests adding fields to models with a temporary default