From ab4f709da4516672b0bd811f2b4d0c4ba9f5b636 Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Mon, 29 Dec 2014 16:23:18 -0500 Subject: [PATCH] Fixed #23581 -- Prevented extraneous DROP DEFAULT statements. Thanks john_scott for the report and Markus Holtermann for review. --- django/db/backends/schema.py | 43 +++++++++++++++++------------------- docs/releases/1.7.2.txt | 2 ++ tests/schema/tests.py | 4 ++++ 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/django/db/backends/schema.py b/django/db/backends/schema.py index 474c1cf8a1..63382adace 100644 --- a/django/db/backends/schema.py +++ b/django/db/backends/schema.py @@ -550,34 +550,31 @@ class BaseDatabaseSchemaEditor(object): # Default change? old_default = self.effective_default(old_field) new_default = self.effective_default(new_field) - if old_default != new_default and not self.skip_default(new_field): - if new_default is None: + needs_database_default = ( + old_default != new_default and + new_default is not None and + not self.skip_default(new_field) + ) + if needs_database_default: + if self.connection.features.requires_literal_defaults: + # Some databases can't take defaults as a parameter (oracle) + # If this is the case, the individual schema backend should + # implement prepare_default actions.append(( - self.sql_alter_column_no_default % { + self.sql_alter_column_default % { "column": self.quote_name(new_field.column), + "default": self.prepare_default(new_default), }, [], )) else: - if self.connection.features.requires_literal_defaults: - # Some databases can't take defaults as a parameter (oracle) - # If this is the case, the individual schema backend should - # implement prepare_default - actions.append(( - self.sql_alter_column_default % { - "column": self.quote_name(new_field.column), - "default": self.prepare_default(new_default), - }, - [], - )) - else: - actions.append(( - self.sql_alter_column_default % { - "column": self.quote_name(new_field.column), - "default": "%s", - }, - [new_default], - )) + actions.append(( + self.sql_alter_column_default % { + "column": self.quote_name(new_field.column), + "default": "%s", + }, + [new_default], + )) # Nullability change? if old_field.null != new_field.null: if new_field.null: @@ -712,7 +709,7 @@ class BaseDatabaseSchemaEditor(object): ) # Drop the default if we need to # (Django usually does not use in-database defaults) - if not self.skip_default(new_field) and new_field.default is not None: + if needs_database_default: sql = self.sql_alter_column % { "table": self.quote_name(model._meta.db_table), "changes": self.sql_alter_column_no_default % { diff --git a/docs/releases/1.7.2.txt b/docs/releases/1.7.2.txt index 50cd0729f2..dcb782fde9 100644 --- a/docs/releases/1.7.2.txt +++ b/docs/releases/1.7.2.txt @@ -181,3 +181,5 @@ Bugfixes * Supported strings escaped by third-party libraries with the ``__html__`` convention in the template engine (:ticket:`23831`). + +* Prevented extraneous ``DROP DEFAULT`` SQL in migrations (:ticket:`23581`). diff --git a/tests/schema/tests.py b/tests/schema/tests.py index 53e67b5647..e9de2131a9 100644 --- a/tests/schema/tests.py +++ b/tests/schema/tests.py @@ -547,6 +547,10 @@ class SchemaTests(TransactionTestCase): strict=True, ) + # This will fail if DROP DEFAULT is inadvertently executed on this + # field which drops the id sequence, at least on PostgreSQL. + Author.objects.create(name='Foo') + def test_rename(self): """ Tests simple altering of fields